/******************************************************************************* * Copyright (c) 2000, 2008 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 * Alena Laskavaia (QNX) - Bug 221224 *******************************************************************************/ package org.eclipse.cdt.debug.mi.core.cdi.model; import org.eclipse.cdt.debug.core.cdi.CDIException; 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.cdi.model.type.ICDIType; import org.eclipse.cdt.debug.mi.core.MIException; import org.eclipse.cdt.debug.mi.core.MISession; import org.eclipse.cdt.debug.mi.core.cdi.MI2CDIException; import org.eclipse.cdt.debug.mi.core.cdi.Session; import org.eclipse.cdt.debug.mi.core.cdi.SourceManager; import org.eclipse.cdt.debug.mi.core.cdi.VariableManager; import org.eclipse.cdt.debug.mi.core.cdi.model.type.IncompleteType; import org.eclipse.cdt.debug.mi.core.command.CommandFactory; import org.eclipse.cdt.debug.mi.core.command.MIDataEvaluateExpression; import org.eclipse.cdt.debug.mi.core.output.MIDataEvaluateExpressionInfo; import org.eclipse.cdt.debug.mi.core.cdi.CdiResources; /** */ public abstract class VariableDescriptor extends CObject implements ICDIVariableDescriptor { // Casting info. String[] castingTypes; int castingIndex; int castingLength; String fName; int position; StackFrame fStackFrame; Thread fThread; int stackdepth; String qualifiedName = null; String fFullName = null; protected ICDIType fType = null; protected String fTypename = null; String sizeof = null; /** * Copy constructor. * @param desc */ public VariableDescriptor(VariableDescriptor desc) { super((Target)desc.getTarget()); fName = desc.getName(); fFullName = desc.fFullName; sizeof = desc.sizeof; fType = desc.fType; try { fStackFrame = (StackFrame)desc.getStackFrame(); fThread = (Thread)desc.getThread(); } catch (CDIException e) { } position = desc.getPosition(); stackdepth = desc.getStackDepth(); castingIndex = desc.getCastingArrayStart(); castingLength = desc.getCastingArrayEnd(); castingTypes = desc.getCastingTypes(); } public VariableDescriptor(Target target, Thread thread, StackFrame stack, String n, String fn, int pos, int depth) { super(target); fName = n; fFullName = fn; fStackFrame = stack; fThread = thread; position = pos; stackdepth = depth; } public int getPosition() { return position; } public int getStackDepth() { return stackdepth; } public void setCastingArrayStart(int start) { castingIndex = start; } public int getCastingArrayStart() { return castingIndex; } public void setCastingArrayEnd(int end) { castingLength = end; } public int getCastingArrayEnd() { return castingLength; } public void setCastingTypes(String[] t) { castingTypes = t; } public String[] getCastingTypes() { return castingTypes; } /** * If the variable was a cast encode the string appropriately for GDB. * For example castin to an array is of 2 elements: * (foo)@2 * @return */ public String encodeVariable() { String fn = getFullName(); if (castingLength > 0 || castingIndex > 0) { StringBuffer buffer = new StringBuffer(); buffer.append("*("); //$NON-NLS-1$ buffer.append('(').append(fn).append(')'); buffer.append('+').append(castingIndex).append(')'); buffer.append('@').append(castingLength); fn = buffer.toString(); } else if (castingTypes != null && castingTypes.length > 0) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < castingTypes.length; ++i) { if (castingTypes[i] != null && castingTypes[i].length() > 0) { if (buffer.length() == 0) { buffer.append('(').append(castingTypes[i]).append(')'); buffer.append(fn); } else { buffer.insert(0, '('); buffer.append(')'); StringBuffer b = new StringBuffer(); b.append('(').append(castingTypes[i]).append(')'); buffer.insert(0, b.toString()); } } } fn = buffer.toString(); } return fn; } public String getFullName() { if (fFullName == null) { fFullName = getName(); } return fFullName; } protected ICDIType getFromTypeCache(String nameType) throws CDIException { StackFrame frame = (StackFrame)getStackFrame(); ICDIType detailedType = null; if (frame != null) { detailedType = frame.getFromTypeCache(nameType); } return detailedType; } protected void addToTypeCache(String nameType, ICDIType typeDefinition) throws CDIException { StackFrame frame = (StackFrame)getStackFrame(); if (frame != null) { frame.addToTypeCache(nameType, typeDefinition); } } /** * @see org.eclipse.cdt.debug.core.cdi.ICDIVariableDescriptor#getName() */ public String getName() { return fName; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getType() */ public ICDIType getType() throws CDIException { if (fType == null) { String nametype = getTypeName(); Target target = (Target)getTarget(); Session session = (Session) target.getSession(); SourceManager sourceMgr = session.getSourceManager(); try { fType = sourceMgr.getType(target, nametype); } catch (CDIException e) { // We are here because the parser did not recognize the type, it may be something // like "builtin_x86_vector" or even a class or a typedef // typedef struct foobar Foobar_t // for this case we need to call "Ptype" for more details. // For speed we save the type definitions in the stackframe, try it first. fType = getFromTypeCache(nametype); if (fType == null) { // Try with ptype. try { String ptype = sourceMgr.getDetailTypeName(target, nametype); fType = sourceMgr.getType(target, ptype); } catch (CDIException ex) { // Some version of gdb does not work on the name of the class // ex: class data foo --> ptype data --> fails // ex: class data foo --> ptype foo --> succeed StackFrame frame = (StackFrame)getStackFrame(); if (frame == null) { Thread thread = (Thread)getThread(); if (thread != null) { frame = thread.getCurrentStackFrame(); } else { frame = ((Thread)target.getCurrentThread()).getCurrentStackFrame(); } } try { String ptype = sourceMgr.getDetailTypeNameFromVariable(frame, getQualifiedName()); fType = sourceMgr.getType(target, ptype); } catch (CDIException e2) { // give up. } } } } if (fType == null) { fType = new IncompleteType(target, nametype); } // cache the result addToTypeCache(nametype, fType); } return fType; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#sizeof() */ public int sizeof() throws CDIException { if (sizeof == null) { Target target = (Target) getTarget(); Thread currentThread = (Thread)target.getCurrentThread(); StackFrame currentFrame = currentThread.getCurrentStackFrame(); StackFrame frame = (StackFrame)getStackFrame(); Thread thread = (Thread)getThread(); synchronized(target.getLock()) { try { if (frame != null) { target.setCurrentThread(frame.getThread(), false); ((Thread)frame.getThread()).setCurrentStackFrame(frame, false); } else if (thread != null) { target.setCurrentThread(thread, false); } MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); String exp = "sizeof(" + getTypeName() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ MIDataEvaluateExpression evaluate = factory.createMIDataEvaluateExpression(exp); mi.postCommand(evaluate); MIDataEvaluateExpressionInfo info = evaluate.getMIDataEvaluateExpressionInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.model.VariableDescriptor.Target_not_responding")); //$NON-NLS-1$ } sizeof = info.getExpression(); } catch (MIException e) { throw new MI2CDIException(e); } finally { if (frame != null) { target.setCurrentThread(currentThread, false); currentThread.setCurrentStackFrame(currentFrame, false); } else if (thread != null) { target.setCurrentThread(currentThread, false); } } } } if (sizeof != null) { try { return Integer.parseInt(sizeof); } catch (NumberFormatException e) { throw new CDIException(e.getMessage()); } } return 0; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#getStackFrame() */ public ICDIStackFrame getStackFrame() throws CDIException { return fStackFrame; } public ICDIThread getThread() throws CDIException { return fThread; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#getTypeName() */ public String getTypeName() throws CDIException { if (fTypename == null) { Target target = (Target)getTarget(); StackFrame frame = (StackFrame)getStackFrame(); if (frame == null) { Thread thread = (Thread)getThread(); if (thread != null) { frame = thread.getCurrentStackFrame(); } else { frame = ((Thread)target.getCurrentThread()).getCurrentStackFrame(); } } Session session = (Session) target.getSession(); SourceManager sourceMgr = session.getSourceManager(); if (frame != null) { fTypename = sourceMgr.getTypeNameFromVariable(frame, getQualifiedName()); } else { fTypename = sourceMgr.getTypeName(target, getQualifiedName()); } } return fTypename; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#getQualifiedName() */ public String getQualifiedName() throws CDIException { if (qualifiedName == null) { qualifiedName = encodeVariable(); } return qualifiedName; } public static boolean equalsCasting(VariableDescriptor var1, VariableDescriptor var2) { String[] castings1 = var1.getCastingTypes(); String[] castings2 = var2.getCastingTypes(); if (castings1 == null && castings2 == null) { return true; } else if (castings1 != null && castings2 != null && castings1.length == castings2.length) { for (int i = 0; i < castings1.length; ++i) { if (!castings1[i].equals(castings2[i])) { return false; } } return true; } return false; } /** * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#equals(ICDIVariableDescriptor) */ public boolean equals(ICDIVariableDescriptor varDesc) { if (varDesc instanceof VariableDescriptor) { VariableDescriptor desc = (VariableDescriptor) varDesc; if (desc.getFullName().equals(getFullName()) && desc.getName().equals(getName()) // see bug #113364 && desc.getCastingArrayStart() == getCastingArrayStart() && desc.getCastingArrayEnd() == getCastingArrayEnd() && equalsCasting(desc, this)) { // Check the threads ICDIThread varThread = null; ICDIThread ourThread = null; try { varThread = desc.getThread(); ourThread = getThread(); } catch (CDIException e) { // ignore } if ((ourThread == null && varThread == null) || (varThread != null && ourThread != null && varThread.equals(ourThread))) { // check the stackFrames ICDIStackFrame varFrame = null; ICDIStackFrame ourFrame = null; try { varFrame = desc.getStackFrame(); ourFrame = getStackFrame(); } catch (CDIException e) { // ignore } if (ourFrame == null && varFrame == null) { return true; } else if (varFrame != null && ourFrame != null && varFrame.equals(ourFrame)) { if (desc.getStackDepth() == getStackDepth()) { if (desc.getPosition() == getPosition()) { return true; } } } } return false; } } return super.equals(varDesc); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#getVariableDescriptorAsArray(org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor, int, int) */ public ICDIVariableDescriptor getVariableDescriptorAsArray(int start, int length) throws CDIException { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); return mgr.getVariableDescriptorAsArray(this, start, length); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor#getVariableDescriptorAsType(org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor, java.lang.String) */ public ICDIVariableDescriptor getVariableDescriptorAsType(String type) throws CDIException { Session session = (Session)getTarget().getSession(); VariableManager mgr = session.getVariableManager(); return mgr.getVariableDescriptorAsType(this, type); } }