| /******************************************************************************* |
| * Copyright (c) 2009, 2010, 2011 Nokia 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: |
| * Nokia - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.edc.internal.services.dsf; |
| |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.Executor; |
| |
| import org.eclipse.cdt.core.IAddress; |
| import org.eclipse.cdt.core.dom.ast.IASTTypeId; |
| import org.eclipse.cdt.core.dom.ast.IBasicType; |
| import org.eclipse.cdt.debug.edc.MemoryUtils; |
| import org.eclipse.cdt.debug.edc.formatter.ITypeContentProvider; |
| import org.eclipse.cdt.debug.edc.formatter.IVariableValueConverter; |
| import org.eclipse.cdt.debug.edc.internal.EDCDebugger; |
| import org.eclipse.cdt.debug.edc.internal.EDCTrace; |
| import org.eclipse.cdt.debug.edc.internal.NumberFormatUtils; |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.ASTEvaluationEngine; |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.IArrayDimensionType; |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.InstructionSequence; |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.Interpreter; |
| import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperandValue; |
| import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager; |
| import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IAggregate; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IArrayType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ICPPBasicType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IEnumeration; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IField; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IInheritance; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType; |
| import org.eclipse.cdt.debug.edc.internal.symbols.ISubroutineType; |
| import org.eclipse.cdt.debug.edc.launch.EDCLaunch; |
| import org.eclipse.cdt.debug.edc.services.AbstractEDCService; |
| import org.eclipse.cdt.debug.edc.services.DMContext; |
| import org.eclipse.cdt.debug.edc.services.IEDCDMContext; |
| import org.eclipse.cdt.debug.edc.services.IEDCExpression; |
| import org.eclipse.cdt.debug.edc.services.IEDCExpressions; |
| import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC; |
| import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider; |
| import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader; |
| import org.eclipse.cdt.debug.edc.symbols.IEnumerator; |
| import org.eclipse.cdt.debug.edc.symbols.IInvalidVariableLocation; |
| import org.eclipse.cdt.debug.edc.symbols.IType; |
| import org.eclipse.cdt.debug.edc.symbols.IVariableLocation; |
| import org.eclipse.cdt.debug.edc.symbols.TypeEngine; |
| import org.eclipse.cdt.debug.edc.symbols.TypeUtils; |
| import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
| import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; |
| import org.eclipse.cdt.dsf.concurrent.Immutable; |
| import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
| import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; |
| import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; |
| import org.eclipse.cdt.dsf.datamodel.DMContexts; |
| import org.eclipse.cdt.dsf.datamodel.IDMContext; |
| import org.eclipse.cdt.dsf.debug.service.IExpressions; |
| import org.eclipse.cdt.dsf.debug.service.IExpressions2; |
| import org.eclipse.cdt.dsf.debug.service.IFormattedValues; |
| import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext; |
| import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext; |
| import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; |
| import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; |
| import org.eclipse.cdt.dsf.service.DsfSession; |
| import org.eclipse.cdt.utils.Addr64; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| |
| public class Expressions extends AbstractEDCService implements IEDCExpressions { |
| |
| public abstract class BaseEDCExpressionDMC extends DMContext implements IEDCExpression { |
| protected String expression; |
| private InstructionSequence parsedExpression; |
| private final ASTEvaluationEngine engine; |
| private final StackFrameDMC frame; |
| protected Number value; |
| protected IStatus valueError; |
| private IVariableLocation valueLocation; |
| private IType valueType; |
| private boolean hasChildren = false; |
| private String valueString; |
| |
| public BaseEDCExpressionDMC(IDMContext parent, String expression, String name) { |
| super(Expressions.this, new IDMContext[] { parent }, name, ((IEDCDMContext)parent).getID() + "." + name); //$NON-NLS-1$ |
| this.expression = expression; |
| frame = DMContexts.getAncestorOfType(parent, StackFrameDMC.class); |
| TypeEngine typeEngine; |
| if (frame != null) { |
| typeEngine = frame.getTypeEngine(); |
| engine = new ASTEvaluationEngine(getEDCServicesTracker(), frame, typeEngine); |
| } else if (parent instanceof ModuleDMC) { |
| IEDCSymbolReader edcSymbolReader = ((ModuleDMC)parent).getSymbolReader(); |
| if (edcSymbolReader instanceof EDCSymbolReader) { |
| IDebugInfoProvider debugInfoProvider |
| = ((EDCSymbolReader)edcSymbolReader).getDebugInfoProvider(); |
| typeEngine = new TypeEngine(getTargetEnvironmentService(), debugInfoProvider); |
| engine = new ASTEvaluationEngine(getEDCServicesTracker(), parent, typeEngine); |
| } else { |
| typeEngine = null; |
| engine = null; |
| } |
| } else { |
| typeEngine = null; |
| engine = null; |
| } |
| } |
| |
| public BaseEDCExpressionDMC(IDMContext parent, String expression) { |
| this(parent, expression, expression); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.services.DMContext#toString() |
| */ |
| @Override |
| public String toString() { |
| return getExpression(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFrame() |
| */ |
| public IFrameDMContext getFrame() { |
| return frame; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getExpression() |
| */ |
| public String getExpression() { |
| return expression; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression() |
| */ |
| public synchronized void evaluateExpression() { |
| if (value != null || valueError != null) |
| return; |
| |
| String expression = getExpression(); |
| |
| if (parsedExpression == null) { |
| try { |
| parsedExpression = engine.getCompiledExpression(expression); |
| } catch (CoreException e) { |
| value = null; |
| valueError = e.getStatus(); |
| valueLocation = null; |
| valueType = null; |
| return; |
| } |
| } |
| |
| if (parsedExpression.getInstructions().length == 0) { |
| value = null; |
| valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, |
| EDCServicesMessages.Expressions_SyntaxError); |
| valueLocation = null; |
| valueType = null; |
| return; |
| } |
| |
| Interpreter interpreter; |
| try { |
| interpreter = engine.evaluateCompiledExpression(parsedExpression); |
| } catch (CoreException e) { |
| value = null; |
| valueError = e.getStatus(); |
| valueLocation = null; |
| valueType = null; |
| return; |
| } |
| |
| OperandValue variableValue = interpreter.getResult(); |
| if (variableValue == null) { |
| value = null; |
| valueError = null; |
| valueLocation = null; |
| valueType = null; |
| return; |
| } |
| |
| valueLocation = variableValue.getValueLocation(); |
| valueType = variableValue.getValueType(); |
| try { |
| value = variableValue.getValue(); |
| valueString = variableValue.getStringValue(); |
| } catch (CoreException e1) { |
| value = null; |
| valueError = e1.getStatus(); |
| return; |
| } |
| |
| // for a structured type or array, return the location and note |
| // that it has children |
| if (valueType instanceof IAggregate && valueLocation != null) { |
| // TODO |
| try { |
| value = variableValue.getValueLocationAddress(); |
| } catch (CoreException e) { |
| value = null; |
| valueError = e.getStatus(); |
| } |
| if (!(value instanceof IInvalidVariableLocation)) |
| hasChildren = true; |
| } |
| |
| // if the location evaluates to NotLive, the types and values do |
| // not matter |
| if (valueLocation instanceof IInvalidVariableLocation) { |
| value = null; |
| valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, |
| ((IInvalidVariableLocation) valueLocation).getMessage()); |
| valueLocation = null; //$NON-NLS-1$ |
| return; |
| } |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFormattedValue(org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext) |
| */ |
| public FormattedValueDMData getFormattedValue(FormattedValueDMContext dmc) { |
| if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(dmc)); } |
| evaluateExpression(); |
| String result = ""; //$NON-NLS-1$ |
| |
| if (valueError != null) { |
| result = valueError.getMessage(); |
| } else if (value != null) { |
| result = value.toString(); |
| |
| IType unqualifiedType = TypeUtils.getUnRefStrippedType(valueType); |
| |
| String temp = null; |
| String formatID = dmc.getFormatID(); |
| |
| // the non-natural formats have expected representations in other |
| // parts of DSF, so be strict about what we return |
| if (formatID.equals(IFormattedValues.HEX_FORMAT)) { |
| temp = NumberFormatUtils.toHexString(value); |
| } else if (formatID.equals(IFormattedValues.OCTAL_FORMAT)) { |
| temp = NumberFormatUtils.toOctalString(value); |
| } else if (formatID.equals(IFormattedValues.BINARY_FORMAT)) { |
| temp = NumberFormatUtils.asBinary(value); |
| } else if (formatID.equals(IFormattedValues.NATURAL_FORMAT)) { |
| // convert non-integer types to original representation |
| if (unqualifiedType instanceof ICPPBasicType) { |
| ICPPBasicType basicType = (ICPPBasicType) unqualifiedType; |
| switch (basicType.getBaseType()) { |
| case ICPPBasicType.t_char: |
| temp = NumberFormatUtils.toCharString(value, valueType); |
| break; |
| case ICPPBasicType.t_wchar_t: |
| temp = NumberFormatUtils.toCharString(value, valueType); |
| break; |
| case ICPPBasicType.t_bool: |
| temp = Boolean.toString(value.longValue() != 0); |
| break; |
| default: |
| // account for other debug formats |
| if (basicType.getName().equals("wchar_t")) { //$NON-NLS-1$ |
| temp = NumberFormatUtils.toCharString(value, valueType); |
| } |
| break; |
| } |
| } else if (unqualifiedType instanceof IAggregate || unqualifiedType instanceof IPointerType) { |
| // show addresses for aggregates and pointers as hex in natural format |
| temp = NumberFormatUtils.toHexString(value); |
| } |
| |
| // TODO: add type suffix if the value cannot fit in |
| // the ordinary range of the base type. |
| // E.g., for an unsigned int, 0xFFFFFFFF should usually be 0xFFFFFFFFU, |
| // and for a long double, 1.E1000 should be 1.E1000L. |
| /* |
| // apply required integer and float suffixes |
| IType unqualifiedType = TypeUtils.getStrippedType(valueType); |
| if (unqualifiedType instanceof ICPPBasicType) { |
| ICPPBasicType basicType = (ICPPBasicType) unqualifiedType; |
| |
| if (basicType.getBaseType() == ICPPBasicType.t_float) { |
| //result += "F"; // no |
| } else if (basicType.getBaseType() == ICPPBasicType.t_double) { |
| if (basicType.isLong() AND actual value does not fit in a double) |
| result += "L"; |
| } else if (basicType.getBaseType() == ICPPBasicType.t_int) { |
| if (basicType.isUnsigned() AND actual value does not fit in a signed int) |
| result += "U"; |
| if (basicType.isLongLong() AND actual value does not fit in a signed int) |
| result += "LL"; |
| else if (basicType.isLong() AND actual value does not fit in a signed int) |
| result += "L"; |
| } |
| } |
| */ |
| |
| // for an enumerator, return the name, if any |
| if (unqualifiedType instanceof IEnumeration) { |
| long enumeratorValue = value.longValue(); |
| |
| IEnumerator enumerator = ((IEnumeration) unqualifiedType).getEnumeratorByValue(enumeratorValue); |
| if (enumerator != null) { |
| if (temp == null) |
| temp = result; |
| |
| temp = enumerator.getName() + " [" + temp + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| if (temp != null) |
| result = temp; |
| |
| // otherwise, leave value as is |
| |
| |
| } |
| if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(result)); } |
| return new FormattedValueDMData(result); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getValueLocation() |
| */ |
| public IVariableLocation getValueLocation() { |
| evaluateExpression(); |
| return getEvaluatedLocation(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluationError() |
| */ |
| public IStatus getEvaluationError() { |
| return valueError; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedValue() |
| */ |
| public Number getEvaluatedValue() { |
| return value; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluatedValueString() |
| */ |
| public String getEvaluatedValueString() { |
| if (valueError != null) |
| return valueError.getMessage(); |
| |
| if (valueString != null) |
| return valueString; |
| |
| valueString = value != null ? value.toString() : ""; //$NON-NLS-1$ |
| return valueString; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#setEvaluatedValueString(java.lang.String) |
| */ |
| public void setEvaluatedValueString(String string) { |
| this.valueString = string; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#setEvaluatedValue(java.lang.Object) |
| */ |
| public void setEvaluatedValue(Number value) { |
| this.value = value; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedLocation() |
| */ |
| public IVariableLocation getEvaluatedLocation() { |
| return valueLocation; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType() |
| */ |
| public IType getEvaluatedType() { |
| return valueType; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getTypeName() |
| */ |
| public String getTypeName() { |
| evaluateExpression(); |
| if (valueType == null) |
| if (valueError != null) |
| return ""; //$NON-NLS-1$ |
| else |
| return ASTEvaluationEngine.UNKNOWN_TYPE; |
| return engine.getTypeEngine().getTypeName(valueType); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#hasChildren() |
| */ |
| public boolean hasChildren() { |
| return this.hasChildren; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getService() |
| */ |
| public Expressions getExpressionsService() { |
| return Expressions.this; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getExecutor() |
| */ |
| public Executor getExecutor() { |
| return getSession().getExecutor(); |
| } |
| |
| } |
| |
| /** A basic expression. */ |
| private class ExpressionDMC extends BaseEDCExpressionDMC { |
| |
| public ExpressionDMC(IDMContext parent, String expression) { |
| super(parent, expression); |
| } |
| |
| |
| public ExpressionDMC(IDMContext parent, String expression, String name) { |
| super(parent, expression, name); |
| } |
| |
| /** |
| * There is no casting on a vanilla expression. |
| * @return <code>null</code> |
| */ |
| public CastInfo getCastInfo() { |
| return null; |
| } |
| |
| |
| } |
| |
| /** A casted or array-displayed expression. */ |
| private class CastedExpressionDMC extends BaseEDCExpressionDMC implements ICastedExpressionDMContext { |
| |
| private final CastInfo castInfo; |
| /** if non-null, interpret result as this type rather than the raw expression's type */ |
| private IType castType = null; |
| private IStatus castError; |
| |
| public CastedExpressionDMC(IEDCExpression exprDMC, String expression, String name, CastInfo castInfo) { |
| super(exprDMC, name); |
| this.castInfo = castInfo; |
| |
| String castType = castInfo.getTypeString(); |
| |
| String castExpression = expression; |
| |
| // If changing type, assume it's reinterpret_cast<>. |
| // Once we support RTTI, this should be dynamic_cast<> when casting |
| // class pointers to class pointers. |
| if (castType != null) { |
| if (castInfo.getArrayCount() > 0) { |
| castType += "[]"; //$NON-NLS-1$ |
| // Force non-pointer expressions to be pointers. |
| exprDMC.evaluateExpression(); |
| IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType()); |
| if (exprType != null) { |
| if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) { |
| expression = "&" + expression; //$NON-NLS-1$ |
| } |
| } |
| } |
| castExpression = "reinterpret_cast<" + castType +">(" + expression + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } else if (castInfo.getArrayCount() > 0) { |
| // For arrays, be sure the OperatorSubscript accepts the base type. |
| // Force non-pointer expressions to be pointers. |
| exprDMC.evaluateExpression(); |
| IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType()); |
| if (exprType != null) { |
| if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) { |
| // cast to pointer if not already one (cast to array is not valid C/C++ but we support it) |
| castExpression = "(" + exprDMC.getTypeName() + "[])&" + expression; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| this.expression = castExpression; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression() |
| */ |
| public void evaluateExpression() { |
| if (castError != null) { |
| return; |
| } |
| |
| super.evaluateExpression(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType() |
| */ |
| public IType getEvaluatedType() { |
| if (castType != null) |
| return castType; |
| return super.getEvaluatedType(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext#getCastInfo() |
| */ |
| public CastInfo getCastInfo() { |
| return castInfo; |
| } |
| } |
| |
| public class ExpressionData implements IExpressionDMData { |
| |
| private final IEDCExpression dmc; |
| private String typeName = ""; |
| |
| public ExpressionData(IEDCExpression dmc) { |
| this.dmc = dmc; |
| if (dmc != null) |
| this.typeName = dmc.getTypeName(); |
| } |
| |
| public BasicType getBasicType() { |
| BasicType basicType = BasicType.unknown; |
| if (dmc == null) |
| return basicType; |
| |
| IType type = dmc.getEvaluatedType(); |
| type = TypeUtils.getStrippedType(type); |
| if (type instanceof IArrayType) { |
| basicType = BasicType.array; |
| } |
| else if (type instanceof IBasicType) { |
| basicType = BasicType.basic; |
| } |
| else if (type instanceof ICompositeType) { |
| basicType = BasicType.composite; |
| } |
| else if (type instanceof IEnumeration) { |
| basicType = BasicType.enumeration; |
| } |
| else if (type instanceof IPointerType) { |
| basicType = BasicType.pointer; |
| } |
| else if (type instanceof ISubroutineType) { |
| basicType = BasicType.function; |
| } |
| return basicType; |
| } |
| |
| public String getEncoding() { |
| return null; |
| } |
| |
| public Map<String, Integer> getEnumerations() { |
| return null; |
| } |
| |
| public String getName() { |
| if (dmc != null) |
| return dmc.getName(); |
| else |
| return ""; //$NON-NLS-1$ |
| } |
| |
| public IRegisterDMContext getRegister() { |
| return null; |
| } |
| |
| public String getTypeId() { |
| return TYPEID_INTEGER; |
| } |
| |
| public String getTypeName() { |
| return typeName; |
| } |
| |
| } |
| |
| protected static class InvalidContextExpressionDMC extends AbstractDMContext implements IExpressionDMContext { |
| private final String expression; |
| |
| public InvalidContextExpressionDMC(String sessionId, String expr, IDMContext parent) { |
| super(sessionId, new IDMContext[] { parent }); |
| expression = expr; |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| return super.baseEquals(other) && expression == null ? ((InvalidContextExpressionDMC) other) |
| .getExpression() == null : expression.equals(((InvalidContextExpressionDMC) other).getExpression()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return expression == null ? super.baseHashCode() : super.baseHashCode() ^ expression.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return baseToString() + ".invalid_expr[" + expression + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public String getExpression() { |
| return expression; |
| } |
| } |
| |
| public class ExpressionDMAddress implements IExpressionDMLocation { |
| |
| private final IVariableLocation valueLocation; |
| |
| public ExpressionDMAddress(IExpressionDMContext exprContext) { |
| if (exprContext instanceof IEDCExpression) |
| valueLocation = ((IEDCExpression) exprContext).getValueLocation(); |
| else |
| valueLocation = null; |
| } |
| |
| public IAddress getAddress() { |
| if (valueLocation != null) { |
| IAddress address = valueLocation.getAddress(); |
| if (address != null) |
| return address; |
| } |
| return new Addr64(BigInteger.ZERO); |
| } |
| |
| public int getSize() { |
| return 4; |
| } |
| |
| public String getLocation() { |
| if (valueLocation instanceof IInvalidVariableLocation) { |
| return ((IInvalidVariableLocation)valueLocation).getMessage(); |
| } |
| if (valueLocation == null) |
| return ""; //$NON-NLS-1$ |
| return valueLocation.getLocationName(); |
| } |
| |
| } |
| |
| public Expressions(DsfSession session) { |
| super(session, new String[] { IExpressions.class.getName(), Expressions.class.getName(), IExpressions2.class.getName() }); |
| } |
| |
| public boolean canWriteExpression(IEDCExpression expressionDMC) { |
| EDCLaunch launch = EDCLaunch.getLaunchForSession(getSession().getId()); |
| if (launch.isSnapshotLaunch()) |
| return false; |
| IVariableValueConverter converter = getCustomValueConverter(expressionDMC); |
| if (converter != null) |
| return converter.canEditValue(); |
| |
| return !isComposite(expressionDMC); |
| } |
| |
| public void canWriteExpression(IExpressionDMContext exprContext, DataRequestMonitor<Boolean> rm) { |
| IEDCExpression expressionDMC = (IEDCExpression) exprContext; |
| rm.setData(canWriteExpression(expressionDMC)); |
| rm.done(); |
| } |
| |
| private boolean isComposite(IEDCExpression expressionDMC) { |
| IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType()); |
| return exprType instanceof ICompositeType; |
| } |
| |
| public IExpressionDMContext createExpression(IDMContext context, String expression) { |
| StackFrameDMC frameDmc = DMContexts.getAncestorOfType(context, StackFrameDMC.class); |
| |
| if (frameDmc != null) { |
| return new ExpressionDMC(frameDmc, expression); |
| } else if (context instanceof IModuleDMContext) { |
| return new ExpressionDMC(context, expression); |
| } |
| return new InvalidContextExpressionDMC(getSession().getId(), expression, context); |
| } |
| |
| class CastInfoCachedData { |
| |
| private CastInfo info; |
| |
| private IType type; |
| private IStatus error; |
| private StackFrameDMC frameDmc; |
| |
| public CastInfoCachedData(ExpressionDMC exprDMC, CastInfo info) { |
| this.info = info; |
| this.frameDmc = DMContexts.getAncestorOfType(exprDMC, StackFrameDMC.class); |
| } |
| |
| public String getTypeString() { |
| return info.getTypeString(); |
| } |
| |
| public int getArrayStartIndex() { |
| return info.getArrayStartIndex(); |
| } |
| |
| public int getArrayCount() { |
| return info.getArrayCount(); |
| } |
| |
| /** |
| * Get the compiled type |
| * @return the type |
| */ |
| public IType getType() { |
| if (info.getTypeString() == null) |
| return null; |
| |
| if (type == null && error == null) { |
| if (frameDmc != null) { |
| ASTEvaluationEngine engine = new ASTEvaluationEngine(getEDCServicesTracker(), frameDmc, frameDmc.getTypeEngine()); |
| try { |
| IASTTypeId typeId = engine.getCompiledType(info.getTypeString()); |
| type = engine.getTypeEngine().getTypeForTypeId(typeId); |
| } catch (CoreException e) { |
| error = e.getStatus(); |
| } |
| } else { |
| error = EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotCastOutsideFrame, null); |
| } |
| } |
| return type; |
| } |
| |
| /** |
| * @return the error |
| */ |
| public IStatus getError() { |
| if (type == null && error == null) { |
| getType(); |
| } |
| return error; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.dsf.debug.service.IExpressions2#createCastedExpression(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext) |
| */ |
| public ICastedExpressionDMContext createCastedExpression(IExpressionDMContext exprDMC, |
| CastInfo castInfo) { |
| |
| // then apply the casting stuff |
| if (exprDMC instanceof IEDCExpression) { |
| CastedExpressionDMC castedDMC = new CastedExpressionDMC((IEDCExpression) exprDMC, |
| exprDMC.getExpression(), ((IEDCExpression) exprDMC).getName(), castInfo); |
| return castedDMC; |
| } else { |
| assert false; |
| return null; |
| } |
| } |
| |
| /* |
| public void createCastedExpression(IDMContext context, String expression, |
| ICastedExpressionDMContext castDMC, IArrayCastedExpressionDMContext arrayCastDMC, |
| DataRequestMonitor<IExpressionDMContext> rm) { |
| |
| // create an ordinary expression... |
| IExpressionDMContext exprDMC = createExpression(context, expression); |
| |
| // then apply the casting stuff |
| if (exprDMC instanceof ExpressionDMC |
| && (castDMC == null || castDMC instanceof CastedExpressionDMContext) |
| && (arrayCastDMC == null || arrayCastDMC instanceof ArrayCastedExpressionDMContext)) { |
| ExpressionDMC expressionDMC = ((ExpressionDMC) exprDMC); |
| if (castDMC != null) |
| expressionDMC.setCastToType((CastedExpressionDMContext) castDMC); |
| if (arrayCastDMC != null) |
| expressionDMC.setArrayCast((ArrayCastedExpressionDMContext) arrayCastDMC); |
| rm.setData(expressionDMC); |
| rm.done(); |
| } else { |
| assert false; |
| rm.setStatus(EDCDebugger.dsfRequestFailedStatus("unexpected cast information", null)); |
| rm.done(); |
| } |
| } |
| */ |
| |
| public void getBaseExpressions(IExpressionDMContext exprContext, DataRequestMonitor<IExpressionDMContext[]> rm) { |
| rm.setData(new IEDCExpression[0]); |
| rm.done(); |
| } |
| |
| public void getExpressionAddressData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMAddress> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| if (exprContext instanceof IEDCExpression) |
| rm.setData(new ExpressionDMAddress(exprContext)); |
| else |
| rm.setData(new ExpressionDMAddress(null)); |
| rm.done(); |
| } |
| }, rm); |
| } |
| |
| public void getExpressionData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMData> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| if (exprContext instanceof IEDCExpression) |
| rm.setData(new ExpressionData((IEDCExpression) exprContext)); |
| else |
| rm.setData(new ExpressionData(null)); |
| rm.done(); |
| } |
| }, rm); |
| } |
| |
| public void getSubExpressionCount(final IExpressionDMContext exprContext, final DataRequestMonitor<Integer> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| // handle array casts |
| CastInfo cast = null; |
| if (exprContext instanceof IEDCExpression && (cast = ((IEDCExpression) exprContext).getCastInfo()) != null) { |
| if (cast.getArrayCount() > 0) { |
| if (((IEDCExpression)exprContext).getEvaluationError() != null) { |
| rm.setData(0); |
| rm.done(); |
| return; |
| } |
| rm.setData(cast.getArrayCount()); |
| rm.done(); |
| return; |
| } |
| } |
| |
| if (!(exprContext instanceof IEDCExpression)) { |
| rm.setData(0); |
| rm.done(); |
| return; |
| } |
| |
| IEDCExpression expr = (IEDCExpression) exprContext; |
| |
| // if expression has no evaluated value, then it has not yet been evaluated |
| if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) { |
| expr.evaluateExpression(); |
| } |
| |
| IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType()); |
| |
| // to expand it, it must either be a pointer, a reference to an aggregate, |
| // or an aggregate |
| boolean pointerType = exprType instanceof IPointerType; |
| boolean referenceType = exprType instanceof IReferenceType; |
| IType pointedTo = null; |
| if (referenceType) |
| pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType()); |
| |
| if (!(exprType instanceof IAggregate) && !pointerType && |
| !(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) { |
| rm.setData(0); |
| rm.done(); |
| return; |
| } |
| |
| ITypeContentProvider customProvider = |
| FormatExtensionManager.instance().getTypeContentProvider(exprType); |
| if (customProvider != null) { |
| try { |
| rm.setData(customProvider.getChildCount(expr)); |
| rm.done(); |
| return; |
| } catch (Throwable e) { |
| } |
| } |
| |
| // TODO: maybe cache these subexpressions; they are just requested again in #getSubExpressions() |
| getSubExpressions(exprContext, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>( |
| getExecutor(), rm) { |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.dsf.concurrent.RequestMonitor#handleSuccess() |
| */ |
| @Override |
| protected void handleSuccess() { |
| rm.setData(getData().length); |
| rm.done(); |
| } |
| }); |
| } |
| }, rm); |
| } |
| |
| public void getSubExpressions(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMContext[]> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| if (!(exprContext instanceof IEDCExpression) || ((IEDCExpression) exprContext).getFrame() == null) { |
| rm.setData(new IEDCExpression[0]); |
| rm.done(); |
| return; |
| } |
| |
| IEDCExpression expr = (IEDCExpression) exprContext; |
| |
| // if expression has no evaluated value, then it has not yet been evaluated |
| if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) { |
| expr.evaluateExpression(); |
| } |
| |
| StackFrameDMC frame = (StackFrameDMC) expr.getFrame(); |
| IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType()); |
| |
| // if casted to an array, convert thusly |
| CastInfo castInfo = expr.getCastInfo(); |
| if (castInfo != null && castInfo.getArrayCount() > 0) { |
| try { |
| exprType = frame.getTypeEngine().convertToArrayType(exprType, castInfo.getArrayCount()); |
| } catch (CoreException e) { |
| rm.setStatus(e.getStatus()); |
| rm.done(); |
| return; |
| } |
| } |
| |
| |
| // to expand it, it must either be a pointer, a reference to an aggregate, |
| // or an aggregate |
| boolean pointerType = exprType instanceof IPointerType; |
| boolean referenceType = exprType instanceof IReferenceType; |
| IType pointedTo = null; |
| if (referenceType) { |
| pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType()); |
| exprType = pointedTo; |
| } |
| |
| if (!(exprType instanceof IAggregate) && !pointerType && |
| !(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) { |
| rm.setData(new IEDCExpression[0]); |
| rm.done(); |
| return; |
| } |
| |
| ITypeContentProvider customProvider = |
| FormatExtensionManager.instance().getTypeContentProvider(exprType); |
| if (customProvider != null) { |
| getSubExpressions(expr, frame, exprType, customProvider, rm); |
| } |
| else |
| getSubExpressions(expr, rm); |
| } |
| }, rm); |
| } |
| |
| public void getSubExpressions(final IExpressionDMContext exprContext, final int startIndex_, final int length_, |
| final DataRequestMonitor<IExpressionDMContext[]> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| getSubExpressions(exprContext, new DataRequestMonitor<IExpressionDMContext[]>(getExecutor(), rm) { |
| @Override |
| protected void handleSuccess() { |
| IExpressionDMContext[] allExprs = getData(); |
| if (startIndex_ == 0 && length_ >= allExprs.length) { |
| rm.setData(allExprs); |
| rm.done(); |
| } else { |
| int startIndex = startIndex_, length = length_; |
| if (startIndex > allExprs.length) { |
| startIndex = allExprs.length; |
| length = 0; |
| } else if (startIndex + length > allExprs.length) { |
| length = allExprs.length - startIndex; |
| if (length < 0) |
| length = 0; |
| } |
| |
| IExpressionDMContext[] result = new IExpressionDMContext[length]; |
| System.arraycopy(allExprs, startIndex, result, 0, length); |
| rm.setData(result); |
| rm.done(); |
| } |
| } |
| }); |
| } |
| }, rm); |
| } |
| |
| private void getSubExpressions(final IEDCExpression expr, final StackFrameDMC frame, |
| final IType exprType, final ITypeContentProvider customProvider, |
| final DataRequestMonitor<IExpressionDMContext[]> rm) { |
| |
| List<IExpressionDMContext> children = new ArrayList<IExpressionDMContext>(); |
| Iterator<IExpressionDMContext> childIterator; |
| try { |
| childIterator = customProvider.getChildIterator(expr); |
| while (childIterator.hasNext() && !rm.isCanceled()) { |
| children.add(childIterator.next()); |
| } |
| rm.setData(children.toArray(new IExpressionDMContext[children.size()])); |
| rm.done(); |
| } catch (CoreException e) { |
| // Checked exception. But we don't want to pass the error up as it |
| // would make the variable (say, a structure) not expandable on UI. |
| // Just resort to the normal formatting. |
| getSubExpressions(expr, rm); |
| } catch (Throwable e) { |
| // unexpected error. log it. |
| EDCDebugger.getMessageLogger().logError( |
| EDCServicesMessages.Expressions_ErrorInVariableFormatter + customProvider.getClass().getName(), e); |
| |
| // default to normal formatting |
| getSubExpressions(expr, rm); |
| } |
| } |
| |
| private void getSubExpressions(final IEDCExpression expr, |
| final DataRequestMonitor<IExpressionDMContext[]> rm) { |
| rm.setData(getLogicalSubExpressions(expr)); |
| rm.done(); |
| } |
| |
| /** |
| * Get the logical subexpressions for the given expression context. We want |
| * to skip unnecessary nodes, e.g., a pointer to a composite, and directly |
| * show the object contents. |
| * @param expr the expression from which to start |
| * @return array of children |
| */ |
| public IEDCExpression[] getLogicalSubExpressions(IEDCExpression expr) { |
| |
| IType exprType = TypeUtils.getUnRefStrippedType(expr.getEvaluatedType()); |
| |
| // cast to array? |
| CastInfo castInfo = expr.getCastInfo(); |
| if (castInfo != null && castInfo.getArrayCount() > 0) { |
| |
| String exprName = expr.getExpression(); |
| |
| // in case of casts, need to resolve that before dereferencing, so be safe |
| if (exprName.contains("(")) //$NON-NLS-1$ |
| exprName = '(' + exprName + ')'; |
| |
| long lowerBound = castInfo.getArrayStartIndex(); |
| long count = castInfo.getArrayCount(); |
| |
| List<IEDCExpression> arrayChildren = new ArrayList<IEDCExpression>(); |
| for (int i = 0; i < count; i++) { |
| String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), (exprName + arrayElement), |
| expr.getName() + arrayElement); |
| IEDCExpression exprChild = newExpr; //$NON-NLS-1$ //$NON-NLS-2$ |
| if (exprChild != null) { |
| arrayChildren.add(exprChild); |
| } |
| } |
| |
| return arrayChildren.toArray(new IEDCExpression[arrayChildren.size()]); |
| } |
| |
| if (exprType instanceof IPointerType) { |
| // automatically dereference a pointer |
| String exprName = expr.getExpression(); |
| IType typePointedTo = TypeUtils.getStrippedType(exprType.getType()); |
| |
| // Try to resolve opaque pointer. |
| // Note this may take some time depending on symbol file size. |
| // ........05/19/11 |
| // |
| if (TypeUtils.isOpaqueType(typePointedTo)) { |
| final Symbols symService = getService(Symbols.class); |
| assert symService != null; |
| |
| final ISymbolDMContext symCtx = DMContexts.getAncestorOfType(expr, ISymbolDMContext.class); |
| if (symCtx != null) { |
| final ICompositeType[] resolved = {null}; |
| final IType original = typePointedTo; |
| Job j = new Job("Resolving opaque type" + original.getName()) { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| monitor.beginTask("Resolving opaque type: " + original.getName(), IProgressMonitor.UNKNOWN); |
| resolved[0] = symService.resolveOpaqueType(symCtx, (ICompositeType)original); |
| monitor.done(); |
| return Status.OK_STATUS; |
| }}; |
| |
| j.schedule(); |
| try { |
| j.join(); |
| } catch (InterruptedException e) { |
| // ignore |
| } |
| |
| if (resolved[0] != null) { |
| typePointedTo = resolved[0]; |
| |
| // Make the pointer type points to the resolved type |
| // so that we won't need to resolve the opaque type again |
| // and again. |
| exprType.setType(resolved[0]); |
| } |
| } |
| } |
| |
| // If expression name already starts with "&" (e.g. "&struct"), indirect it first |
| boolean indirected = false; |
| |
| IEDCExpression exprChild; |
| |
| if (exprName.startsWith("&")) { //$NON-NLS-1$ |
| exprName = exprName.substring(1); |
| IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), exprName); |
| exprChild = newExpr; |
| indirected = true; |
| } |
| else { |
| // avoid dereferencing void pointer |
| if (typePointedTo instanceof ICPPBasicType |
| && ((ICPPBasicType) typePointedTo).getBaseType() == ICPPBasicType.t_void) { |
| return new IEDCExpression[0]; |
| } |
| |
| // do not dereference null either |
| if (expr.getEvaluatedValue() != null && expr.getEvaluatedValue().intValue() == 0) |
| return new IEDCExpression[0]; |
| IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), ("*" + exprName), "*" + expr.getName()); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| // a pointer type has one child |
| exprChild = newExpr; //$NON-NLS-1$ |
| } |
| |
| return doGetLogicalSubExpressions(exprChild, typePointedTo, indirected); |
| } |
| else if (exprType instanceof IReferenceType) { |
| // and bypass a reference |
| |
| IType typePointedTo = TypeUtils.getStrippedType(exprType.getType()); |
| return doGetLogicalSubExpressions(expr, typePointedTo, false); |
| }else { |
| // normal aggregate, just do it |
| return doGetLogicalSubExpressions(expr, exprType, false); |
| } |
| |
| } |
| |
| /** |
| * Get the logical subexpressions for the given expression context and string |
| * @param expr the expression from which to start |
| * @param exprType the type in which to consider the expression |
| * @param indirected if true, the expression was already indirected, as opposed to what the expression says |
| * @return |
| */ |
| private IEDCExpression[] doGetLogicalSubExpressions(IEDCExpression expr, IType exprType, boolean indirected) { |
| ArrayList<IEDCExpression> exprList = new ArrayList<IEDCExpression>(); |
| IEDCExpression exprChild; |
| |
| String expression = expr.getExpression(); |
| |
| // in case of casts, need to resolve that before dereferencing, so be safe |
| if (expression.contains("(")) //$NON-NLS-1$ |
| expression = '(' + expression + ')'; |
| |
| /* |
| // cast to array? |
| CastInfo castInfo = expr.getCastInfo(); |
| if (castInfo != null && castInfo.getArrayCount() > 0) { |
| long lowerBound = castInfo.getArrayStartIndex(); |
| long count = castInfo.getArrayCount(); |
| for (int i = 0; i < count; i++) { |
| exprChild = createDerivedExpression(expr, exprName + "[" + (i + lowerBound) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } |
| |
| } |
| else*/ if (exprType instanceof ICompositeType) { |
| // an artifact of following a pointer to a structure is that the |
| // name starts with '*' |
| if (expression.startsWith("*")) { //$NON-NLS-1$ |
| if (expression.startsWith("**")) |
| expression = "(" + expression.substring(1) + ")->"; //$NON-NLS-1$ |
| else |
| expression = expression.substring(1) + "->"; //$NON-NLS-1$ |
| } else { |
| expression = expression + '.'; //$NON-NLS-1$ |
| } |
| |
| // for each field, evaluate an expression, then shorten the name |
| ICompositeType compositeType = (ICompositeType) exprType; |
| |
| for (IField field : compositeType.getFields()) { |
| String fieldName = field.getName(); |
| if (fieldName.length() == 0) { |
| // This makes an invalid expression |
| // The debug info provider should have filtered out or renamed such fields |
| assert false; |
| continue; |
| } |
| exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName); |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } |
| |
| for (IInheritance inherited : compositeType.getInheritances()) { |
| String inheritedName = inherited.getName(); |
| if (inheritedName.length() == 0) { |
| // This makes an invalid expression |
| // The debug info provider should have filtered out or renamed such fields |
| assert false; // couldn't this be the case for an anonymous member, like a union? |
| } else if (!inheritedName.contains("<")) { |
| exprChild = new ExpressionDMC(expr.getFrame(), expression + inheritedName, inheritedName); |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } else { |
| IType inheritedType = inherited.getType(); |
| if (inheritedType instanceof ICompositeType) { |
| for (IField field : ((ICompositeType)inheritedType).getFields()) { |
| String fieldName = field.getName(); |
| if (fieldName.length() == 0) { |
| // This makes an invalid expression |
| // The debug info provider should have filtered out or renamed such fields |
| assert false; |
| continue; |
| } |
| exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName); |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } |
| } |
| } |
| } |
| |
| } |
| else if (exprType instanceof IArrayType) { |
| IArrayType arrayType = (IArrayType) exprType; |
| |
| if (arrayType.getBoundsCount() > 0) { |
| long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 |
| ? expr.getCastInfo().getArrayStartIndex() : 0; |
| long upperBound = arrayType.getBound(0).getBoundCount(); |
| if (upperBound == 0) |
| upperBound = 1; |
| for (int i = 0; i < upperBound; i++) { |
| String arrayElementName = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElementName, |
| expr.getName() + arrayElementName); |
| exprChild = newExpr; |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } |
| } |
| } |
| else if (exprType instanceof IArrayDimensionType) { |
| IArrayDimensionType arrayDimensionType = (IArrayDimensionType) exprType; |
| IArrayType arrayType = arrayDimensionType.getArrayType(); |
| |
| if (arrayType.getBoundsCount() > arrayDimensionType.getDimensionCount()) { |
| long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 |
| ? expr.getCastInfo().getArrayStartIndex() : 0; |
| long upperBound = arrayType.getBound(arrayDimensionType.getDimensionCount()).getBoundCount(); |
| for (int i = 0; i < upperBound; i++) { |
| String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElement, |
| expr.getName() + arrayElement); |
| exprChild = newExpr; |
| if (exprChild != null) { |
| exprList.add(exprChild); |
| } |
| } |
| } |
| } |
| else { |
| // nothing interesting |
| exprList.add(expr); |
| } |
| |
| return exprList.toArray(new IEDCExpression[exprList.size()]); |
| } |
| |
| @Immutable |
| private static class ExpressionChangedDMEvent extends AbstractDMEvent<IExpressionDMContext> implements IExpressionChangedDMEvent { |
| ExpressionChangedDMEvent(IExpressionDMContext expression) { |
| super(expression); |
| } |
| } |
| |
| public void writeExpression(final IExpressionDMContext exprContext, final String expressionValue, final String formatId, final RequestMonitor rm) { |
| |
| asyncExec(new Runnable() { |
| public void run() { |
| IEDCExpression expressionDMC = (IEDCExpression) exprContext; |
| if (isComposite(expressionDMC)) { |
| rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotModifyCompositeValue, null)); |
| rm.done(); |
| return; |
| } |
| |
| IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType()); |
| |
| // first try to get value by format as BigInteger |
| Number number = NumberFormatUtils.parseIntegerByFormat(expressionValue, formatId); |
| if (number == null) { |
| IEDCExpression temp = (IEDCExpression) createExpression(expressionDMC.getFrame(), expressionValue); |
| temp.evaluateExpression(); |
| number = temp.getEvaluatedValue(); |
| |
| if (number == null) { |
| rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotParseExpression, null)); |
| rm.done(); |
| return; |
| } |
| } |
| |
| BigInteger value = null; |
| try { |
| value = MemoryUtils.convertValueToMemory(exprType, number); |
| } catch (CoreException e) { |
| rm.setStatus(e.getStatus()); |
| rm.done(); |
| return; |
| } |
| |
| IVariableLocation variableLocation = expressionDMC.getValueLocation(); |
| if (variableLocation == null) { |
| rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_ExpressionNoLocation, null)); |
| rm.done(); |
| return; |
| } |
| |
| try { |
| variableLocation.writeValue(exprType.getByteSize(), value); |
| getSession().dispatchEvent(new ExpressionChangedDMEvent(exprContext), getProperties()); |
| } catch (CoreException e) { |
| rm.setStatus(e.getStatus()); |
| } |
| |
| rm.done(); |
| } |
| }, rm); |
| |
| } |
| |
| public void getAvailableFormats(IFormattedDataDMContext formattedDataContext, DataRequestMonitor<String[]> rm) { |
| rm.setData(new String[] { IFormattedValues.NATURAL_FORMAT, IFormattedValues.DECIMAL_FORMAT, |
| IFormattedValues.HEX_FORMAT, IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT }); |
| rm.done(); |
| } |
| |
| public void getFormattedExpressionValue(final FormattedValueDMContext formattedDataContext, |
| final DataRequestMonitor<FormattedValueDMData> rm) { |
| asyncExec(new Runnable() { |
| public void run() { |
| try { |
| rm.setData(getFormattedExpressionValue(formattedDataContext)); |
| rm.done(); |
| } catch (CoreException ce) { |
| rm.setStatus(ce.getStatus()); |
| rm.done(); |
| return; |
| } |
| } |
| }, rm); |
| } |
| |
| public String getExpressionValueString(IExpressionDMContext expression, String format) throws CoreException { |
| FormattedValueDMContext formattedDataContext = getFormattedValueContext(expression, format); |
| FormattedValueDMData formattedValue = getFormattedExpressionValue(formattedDataContext); |
| |
| return formattedValue != null ? formattedValue.getFormattedValue() : ""; |
| } |
| |
| public FormattedValueDMData getFormattedExpressionValue(FormattedValueDMContext formattedDataContext) throws CoreException { |
| IDMContext idmContext = formattedDataContext.getParents()[0]; |
| FormattedValueDMData formattedValue = null; |
| IEDCExpression exprDMC = null; |
| |
| if (idmContext instanceof IEDCExpression) { |
| exprDMC = (IEDCExpression) formattedDataContext.getParents()[0]; |
| |
| exprDMC.evaluateExpression(); |
| |
| if (exprDMC != null && exprDMC.getEvaluationError() != null) { |
| throw new CoreException(exprDMC.getEvaluationError()); |
| } |
| |
| formattedValue = exprDMC.getFormattedValue(formattedDataContext); // must call this to get type |
| |
| if (formattedDataContext.getFormatID().equals(IFormattedValues.NATURAL_FORMAT)) |
| { |
| IVariableValueConverter customConverter = getCustomValueConverter(exprDMC); |
| if (customConverter != null) { |
| FormattedValueDMData customFormattedValue = null; |
| try { |
| customFormattedValue = new FormattedValueDMData(customConverter.getValue(exprDMC)); |
| formattedValue = customFormattedValue; |
| } |
| catch (CoreException e) { |
| // Checked exception like failure in reading memory. just re-throw |
| // it so it shows up in the variables view. |
| throw e; |
| } catch (Throwable t) { |
| // Other unexpected errors, usually bug in the formatter. Log it |
| // so that user will be able to see and report the bug. |
| // Meanwhile default to normal formatting so that user won't see |
| // such error in Variable UI. |
| EDCDebugger.getMessageLogger().logError( |
| EDCServicesMessages.Expressions_ErrorInVariableFormatter + customConverter.getClass().getName(), t); |
| } |
| } |
| } |
| } else |
| formattedValue = new FormattedValueDMData(""); //$NON-NLS-1$ |
| |
| return formattedValue; |
| } |
| |
| private IVariableValueConverter getCustomValueConverter(IEDCExpression exprDMC) { |
| IType exprType = TypeUtils.getUnRefStrippedType(exprDMC.getEvaluatedType()); |
| return FormatExtensionManager.instance().getVariableValueConverter(exprType); |
| } |
| |
| public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext formattedDataContext, |
| String formatId) { |
| return new FormattedValueDMContext(this, formattedDataContext, formatId); |
| } |
| |
| public void getModelData(IDMContext context, DataRequestMonitor<?> rm) { |
| } |
| |
| public String getExpressionValue(IExpressionDMContext expression) |
| { |
| final StringBuffer holder = new StringBuffer(); |
| FormattedValueDMContext formattedValueContext = getFormattedValueContext(expression, IFormattedValues.NATURAL_FORMAT); |
| getFormattedExpressionValue(formattedValueContext, new DataRequestMonitor<FormattedValueDMData>(ImmediateExecutor.getInstance(), null) { |
| @Override |
| protected void handleSuccess() { |
| holder.append(this.getData().getFormattedValue()); |
| } |
| |
| @Override |
| protected void handleFailure() { |
| // RequestMonitor would by default log any error if it's not explicitly |
| // handled. But we don't want to log those expected errors (checked exceptions) |
| // in such case as creating snapshot. Hence this dummy handler...02/17/10 |
| |
| // DO nothing. |
| } |
| |
| |
| }); |
| return holder.toString(); |
| } |
| |
| public void loadExpressionValues(IExpressionDMContext expression, int depth) |
| { |
| loadExpressionValues(expression, new Integer[] {depth}); |
| } |
| |
| private void loadExpressionValues(IExpressionDMContext expression, final Integer[] depth) |
| { |
| getExpressionValue(expression); |
| if (depth[0] > 0) |
| { |
| getSubExpressions(expression, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>(ImmediateExecutor.getInstance(), null) { |
| |
| @Override |
| protected void handleSuccess() { |
| depth[0] = depth[0] - 1; |
| IExpressions.IExpressionDMContext[] subExpressions = getData(); |
| for (IExpressionDMContext iExpressionDMContext : subExpressions) { |
| loadExpressionValues(iExpressionDMContext, depth); |
| } |
| }}); |
| } |
| } |
| } |