blob: f9f97a3bb0123fd9b996e9f4720329843f534acb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 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.eval.ast.engine.instructions;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.ASTEvalMessages;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Symbols;
import org.eclipse.cdt.debug.edc.internal.symbols.InvalidVariableLocation;
import org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCModules;
import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
import org.eclipse.cdt.debug.edc.services.Stack.EnumeratorDMC;
import org.eclipse.cdt.debug.edc.services.Stack.IVariableEnumeratorContext;
import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
import org.eclipse.cdt.debug.edc.services.Stack.VariableDMC;
import org.eclipse.cdt.debug.edc.symbols.ILocationProvider;
import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
import org.eclipse.cdt.debug.edc.symbols.TypeUtils;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.core.runtime.CoreException;
public class EvaluateID extends SimpleInstruction {
private String name;
private final ICPPASTQualifiedName qualifiedName;
/**
* Constructor for ID (number + variable name) evaluate instruction
*
* @param idExpression
*/
public EvaluateID(IASTIdExpression idExpression) {
IASTName lookupName;
if (idExpression.getName() instanceof ICPPASTQualifiedName) {
// the name has the form namespace::...::variable
qualifiedName = (ICPPASTQualifiedName) idExpression.getName();
lookupName = qualifiedName.getLastName();
} else {
lookupName = idExpression.getName();
qualifiedName = null;
}
name = new String(lookupName.getLookupKey());
}
/**
* Constructor for lookup of a specific literal name
* (presumably a local, like "this")
*
* @param name the literal name
*/
public EvaluateID(String name) {
this.name = name;
this.qualifiedName = null;
}
/**
* Resolve a variable ID
*
* @throws CoreException
*/
@Override
public void execute() throws CoreException {
IDMContext context = getContext();
if (!(context instanceof StackFrameDMC))
throw EDCDebugger.newCoreException(MessageFormat.format(ASTEvalMessages.EvaluateID_CannotResolveName, name));
StackFrameDMC frame = (StackFrameDMC) context;
EDCServicesTracker servicesTracker = frame.getEDCServicesTracker();
IEDCModules modules = servicesTracker.getService(IEDCModules.class);
// check by name for a variable or enumerator
IVariableEnumeratorContext variableOrEnumerator = frame.findVariableOrEnumeratorByName(name, qualifiedName != null ? qualifiedName.getRawSignature() : null, false);
VariableDMC variable = variableOrEnumerator instanceof VariableDMC ?
(VariableDMC)variableOrEnumerator : null;
EnumeratorDMC enumerator = variableOrEnumerator instanceof EnumeratorDMC ?
(EnumeratorDMC)variableOrEnumerator : null;
// This may be called on debugger shutdown, in which case the "modules"
// service may have been shutdown.
if (variable != null && modules != null) {
IVariableLocation valueLocation = null;
ILocationProvider provider = variable.getVariable().getLocationProvider();
IEDCModuleDMContext module = frame.getModule();
if (module != null && provider != null) {
valueLocation = provider.getLocation(servicesTracker, frame, module.toLinkAddress(frame.getInstructionPtrAddress()),
TypeUtils.isConstType(variable.getVariable().getType()));
}
if (valueLocation == null) {
// unhandled
valueLocation = new InvalidVariableLocation(MessageFormat.format(ASTEvalMessages.EvaluateID_NameHasNoLocation, variable.getName()));
}
// create a VariableWithValue and push on the stack
VariableWithValue varWval = new VariableWithValue(servicesTracker, frame, variable.getVariable());
varWval.setValueLocation(valueLocation);
push(varWval);
return;
}
if (enumerator != null) {
// TODO: map IEnumerator to an IEnumeration and use the real type
pushNewValue(fInterpreter.getTypeEngine().getIntegerTypeOfSize(4, true),
enumerator.getEnumerator().getValue());
return;
}
// match against function names visible in the module
Symbols symbolsService = servicesTracker.getService(Symbols.class);
if (symbolsService != null) {
IEDCModuleDMContext module = frame.getModule();
if (module != null) {
String searchName = name;
if (qualifiedName != null)
searchName = qualifiedName.getRawSignature();
List<IAddress> addresses = symbolsService.getFunctionAddress(module, searchName);
if (addresses.size() > 0) {
pushNewValue(fInterpreter.getTypeEngine().getIntegerTypeOfSize(4, false),
addresses.get(0).getValue().longValue());
return;
}
// show the whole qualified name in the exception message
name = searchName;
}
}
// did not find a variable, enumerator, or function to match the expression
throw EDCDebugger.newCoreException(
MessageFormat.format(ASTEvalMessages.EvaluateID_VariableNotFound, name));
}
}