1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

[298883] Support for MacOS version of services

This commit is contained in:
Marc Khouzam 2010-01-10 02:23:38 +00:00
parent 866f945428
commit 44863628a6
9 changed files with 513 additions and 27 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2009 QNX Software Systems and others.
* Copyright (c) 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
@ -9,6 +9,7 @@
* QNX Software Systems - Initial API and implementation
* Windriver and Ericsson - Updated for DSF
* IBM Corporation
* Ericsson - Added support for Mac OS
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.launching;
@ -30,6 +31,7 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactoryNS;
import org.eclipse.cdt.dsf.gdb.service.SessionType;
import org.eclipse.cdt.dsf.gdb.service.macos.MacOSGdbDebugServicesFactory;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
@ -382,6 +384,11 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
}
private boolean isNonStopSupported(String version) {
if (version.contains(LaunchUtils.MACOS_GDB_MARKER)) {
// Mac OS's GDB does not support Non-Stop
return false;
}
if (NON_STOP_FIRST_VERSION.compareTo(version) <= 0) {
return true;
}
@ -394,11 +401,14 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
if (isNonStopSession && isNonStopSupported(version)) {
return new GdbDebugServicesFactoryNS(version);
}
if (version.startsWith("6.6") || //$NON-NLS-1$
version.startsWith("6.7") || //$NON-NLS-1$
version.startsWith("6.8")) { //$NON-NLS-1$
return new GdbDebugServicesFactory(version);
if (version.contains(LaunchUtils.MACOS_GDB_MARKER)) {
// The version string at this point should look like
// 6.3.50-20050815APPLE1346, we extract the gdb version and apple version
String versions [] = version.split(LaunchUtils.MACOS_GDB_MARKER);
if (versions.length == 2) {
return new MacOSGdbDebugServicesFactory(versions[0], versions[1]);
}
}
return new GdbDebugServicesFactory(version);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* Copyright (c) 2010 Ericsson 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ericsson - Initial API and implementation
* Ericsson - Added support for Mac OS
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.launching;
@ -43,6 +44,12 @@ import org.eclipse.debug.core.ILaunchConfiguration;
public class LaunchUtils {
/**
* A prefix that we use to indicate that a GDB version is for MAC OS
* @since 2.1
*/
public static final String MACOS_GDB_MARKER = "APPLE"; //$NON-NLS-1$
/**
* Verify the following things about the project:
* - is a valid project name given
@ -230,6 +237,26 @@ public class LaunchUtils {
version = "6.8"; //$NON-NLS-1$
}
}
// Look for the case of Apple's GDB, since the version must be handled differently
// The format is:
// GNU gdb 6.3.50-20050815 (Apple version gdb-696) (Sat Oct 20 18:20:28 GMT 2007)
// GNU gdb 6.3.50-20050815 (Apple version gdb-966) (Tue Mar 10 02:43:13 UTC 2009)
// GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
// It seems the version that changes is the "Apple version" but we still use both.
// The Mac OS prefix and version are appended to the normal version so the
// returned string has this format: 6.3.50-20050815APPLE1346. The normal version and the
// Apple version are extracted later and passed to the MacOS services factory.
if (versionOutput.indexOf("Apple") != -1) { //$NON-NLS-1$
// Add a prefix to indicate we are dealing with an Apple GDB
version += MACOS_GDB_MARKER;
Pattern aPattern = Pattern.compile(" \\(Apple version gdb-(\\d*)\\)", Pattern.MULTILINE); //$NON-NLS-1$
Matcher aMatcher = aPattern.matcher(versionOutput);
if (aMatcher.find()) {
version += aMatcher.group(1);
}
}
return version;
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2010 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.macos;
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
import org.eclipse.cdt.dsf.mi.service.MIVariableManager;
import org.eclipse.cdt.dsf.service.DsfSession;
/**
* Specific ExpressionService for MacOS
*
* @since 2.1
*/
public class MacOSGDBExpressions extends MIExpressions {
public MacOSGDBExpressions(DsfSession session) {
super(session);
}
@Override
protected MIVariableManager createMIVariableManager() {
return new MacOSGDBVariableManager(getSession(), getServicesTracker());
}
}

View file

@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (c) 2010 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.macos;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.mi.service.MIVariableManager;
import org.eclipse.cdt.dsf.mi.service.command.commands.macos.MacOSMIVarUpdate;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarChange;
import org.eclipse.cdt.dsf.mi.service.command.output.macos.MacOSMIVarUpdateInfo;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
/**
* Specific VariableManager for MacOS
*
* @since 2.1
*/
public class MacOSGDBVariableManager extends MIVariableManager {
public MacOSGDBVariableManager(DsfSession session, DsfServicesTracker tracker) {
super(session, tracker);
}
@Override
protected MIRootVariableObject createRootVariableObject(VariableObjectId id) {
return new MacOSGDBRootVariableObject(id);
}
private class MacOSGDBRootVariableObject extends MIRootVariableObject {
public MacOSGDBRootVariableObject(VariableObjectId id) {
super(id);
}
@Override
public void update(final DataRequestMonitor<Boolean> rm) {
if (isOutOfScope()) {
rm.setData(false);
rm.done();
} else if (currentState != STATE_READY) {
// Object is not fully created or is being updated
// so add RequestMonitor to pending queue
updatesPending.add(rm);
} else if (getOutOfDate() == false) {
rm.setData(false);
rm.done();
} else {
// Object needs to be updated in the back-end
currentState = STATE_UPDATING;
// In GDB, var-update will only report a change if -var-evaluate-expression has
// changed -- in the current format--. This means that situations like
// double z = 1.2;
// z = 1.4;
// Will not report a change if the format is anything else than natural.
// This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
// Since we cache the values of every format, we must know if -any- format has
// changed, not just the current one.
// To solve this, we always do an update in the natural format; I am not aware
// of any case where the natural format would stay the same, but another format
// would change. However, since a var-update update all children as well,
// we must make sure these children are also in the natural format
// The simplest way to do this is that whenever we change the format
// of a variable object, we immediately set it back to natural with a second
// var-set-format command. This is done in the getValue() method
getCommandControl().queueCommand(
new MacOSMIVarUpdate(getRootToUpdate().getControlDMContext(), getGdbName()),
new DataRequestMonitor<MacOSMIVarUpdateInfo>(getSession().getExecutor(), rm) {
@Override
protected void handleCompleted() {
currentState = STATE_READY;
if (isSuccess()) {
setOutOfDate(false);
MIVarChange[] changes = getData().getMIVarChanges();
if (changes.length > 0 && changes[0].isInScope() == false) {
// Object is out-of-scope
outOfScope = true;
// We can delete this root in GDB right away. This is safe, even
// if the root has children, because they are also out-of-scope.
// We -must- also remove this entry from our LRU. If we don't
// we can end-up with a race condition that create this object
// twice, or have an infinite loop while never re-creating the object.
// The can happen if we update a child first then we request
// the root later,
getLRUCache().remove(getInternalId());
rm.setData(true);
rm.done();
} else {
// The root object is now up-to-date, we must parse the changes, if any.
processChanges(changes);
// We only mark this root as updated in our list if it is in-scope.
// For out-of-scope object, we don't ever need to re-update them so
// we don't need to add them to this list.
rootVariableUpdated(MacOSGDBRootVariableObject.this);
rm.setData(false);
rm.done();
}
while (updatesPending.size() > 0) {
DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
pendingRm.setData(false);
pendingRm.done();
}
} else {
// We were not able to update for some reason
rm.setData(false);
rm.done();
while (updatesPending.size() > 0) {
DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
pendingRm.setStatus(getStatus());
pendingRm.done();
}
}
}
});
}
}
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2010 Ericsson 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:
* Marc-Andre Laperle - Added support for Mac OS (separate factory)
* Ericsson - Added a field for the specific Mac OS version scheme
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.macos;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
import org.eclipse.cdt.dsf.service.DsfSession;
/** @since 2.1 */
public class MacOSGdbDebugServicesFactory extends GdbDebugServicesFactory {
// Mac OS has it's own version of GDB, which does not follow the standard GDB version
// We have to be careful not to compare that specific version number scheme with the
// FSF GDB version scheme.
// Use this variable when needing to differentiate between different Mac OS GDBs
private final String fAppleVersion;
public MacOSGdbDebugServicesFactory(String gdbVersion, String appleVersion) {
super(gdbVersion);
fAppleVersion = appleVersion;
}
@Override
protected IExpressions createExpressionService(DsfSession session) {
return new MacOSGDBExpressions(session);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2008 Wind River Systems and others.
* Copyright (c) 2010 Wind River 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
@ -452,7 +452,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
// to the back-end, through the MICommandControl service
// It must be created after the ExpressionService is registered
// since it will need to find it.
varManager = new MIVariableManager(getSession(), getServicesTracker());
varManager = createMIVariableManager();
// Create the meta command cache which will use the variable manager
// to actually send MI commands to the back-end
@ -463,6 +463,16 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
requestMonitor.done();
}
/**
* Creates the MI variable manager to be used by this expression service.
* Overriding classes may override to provide a custom services tracker.
*
* @since 2.1
*/
protected MIVariableManager createMIVariableManager() {
return new MIVariableManager(getSession(), getServicesTracker());
}
/**
* This method shuts down this service. It unregisters the service, stops
* receiving service events, and calls the superclass shutdown() method to

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008 Monta Vista and others.
* Copyright (c) 2010 Monta Vista 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
@ -697,7 +697,7 @@ public class MIVariableManager implements ICommandControl {
}
if (childVar == null) {
childVar = new MIVariableObject(childId, MIVariableObject.this);
childVar = createVariableObject(childId, MIVariableObject.this);
childVar.setGdbName(child.getVarName());
childVar.setExpressionData(
childFullExpression,
@ -914,7 +914,19 @@ public class MIVariableManager implements ICommandControl {
}
}
private class MIRootVariableObject extends MIVariableObject {
/**
* Method to allow to override the MIVariableObject creation
*
* @since 2.1
*/
protected MIVariableObject createVariableObject(VariableObjectId id, MIVariableObject parentObj) {
return new MIVariableObject(id, parentObj);
}
/**
* @since 2.1
*/
public class MIRootVariableObject extends MIVariableObject {
// Only root variables go through the GDB creation process
protected static final int STATE_NOT_CREATED = 10;
@ -925,7 +937,7 @@ public class MIVariableManager implements ICommandControl {
// will have the same control context
private ICommandControlDMContext fControlContext = null;
private boolean outOfDate = false;
private boolean fOutOfDate = false;
// Modifiable descendants are any variable object that is a descendant or itself for
// which the value can change.
@ -940,8 +952,10 @@ public class MIVariableManager implements ICommandControl {
public ICommandControlDMContext getControlDMContext() { return fControlContext; }
public boolean isUpdating() { return currentState == STATE_UPDATING; }
public void markAsOutOfDate() { outOfDate = true; }
public void setOutOfDate(boolean outOfDate) { fOutOfDate = outOfDate; }
public boolean getOutOfDate() { return fOutOfDate; }
// Remember that we must add ourself as a modifiable descendant if our value can change
public void addModifiableDescendant(String gdbName, MIVariableObject descendant) {
@ -1033,7 +1047,7 @@ public class MIVariableManager implements ICommandControl {
// Object is not fully created or is being updated
// so add RequestMonitor to pending queue
updatesPending.add(rm);
} else if (outOfDate == false) {
} else if (getOutOfDate() == false) {
rm.setData(false);
rm.done();
} else {
@ -1063,7 +1077,7 @@ public class MIVariableManager implements ICommandControl {
currentState = STATE_READY;
if (isSuccess()) {
outOfDate = false;
setOutOfDate(false);
MIVarChange[] changes = getData().getMIVarChanges();
if (changes.length > 0 && changes[0].isInScope() == false) {
@ -1088,7 +1102,7 @@ public class MIVariableManager implements ICommandControl {
// We only mark this root as updated in our list if it is in-scope.
// For out-of-scope object, we don't ever need to re-update them so
// we don't need to add them to this list.
updatedRootList.add(MIRootVariableObject.this);
rootVariableUpdated(MIRootVariableObject.this);
rm.setData(false);
rm.done();
@ -1138,9 +1152,16 @@ public class MIVariableManager implements ICommandControl {
} else {
// Variable was never created or was already deleted, no need to do anything.
}
}
}
}
/**
* Method to allow to override the MIRootVariableObject creation.
*
* @since 2.1
*/
protected MIRootVariableObject createRootVariableObject(VariableObjectId id) {
return new MIRootVariableObject(id);
}
/**
@ -1153,8 +1174,10 @@ public class MIVariableManager implements ICommandControl {
*
* Note that if no frameContext is specified (only Execution, or even only Container), which can
* characterize a global variable for example, we will only use the available information.
*
* @since 2.1
*/
private class VariableObjectId {
public class VariableObjectId {
// We don't use the expression context because it is not safe to compare them
// See bug 187718. So we store the expression itself, and it's parent execution context.
String fExpression = null;
@ -1163,6 +1186,9 @@ public class MIVariableManager implements ICommandControl {
// the same frame will have a different level based on the current depth of the stack
Integer fFrameId = null;
public VariableObjectId() {
}
@Override
public boolean equals(Object other) {
if (other instanceof VariableObjectId) {
@ -1220,6 +1246,16 @@ public class MIVariableManager implements ICommandControl {
}
}
/**
* Method to allow to override the VariableObjectId creation.
*
* @since 2.1
*/
protected VariableObjectId createVariableObjectId() {
return new VariableObjectId();
}
/**
* This is the real work horse of managing our objects. Not only must every
* value be unique to get inserted, this also creates an LRU (least recently
@ -1338,6 +1374,34 @@ public class MIVariableManager implements ICommandControl {
fSession.removeServiceEventListener(this);
}
/**
* @since 2.1
*/
protected DsfSession getSession() {
return fSession;
}
/**
* @since 2.1
*/
protected ICommandControl getCommandControl() {
return fCommandControl;
}
/**
* @since 2.1
*/
protected void rootVariableUpdated(MIRootVariableObject rootObj) {
updatedRootList.add(rootObj);
}
/**
* @since 2.1
*/
protected Map<VariableObjectId, MIVariableObject> getLRUCache() {
return lruVariableList;
}
/**
* This method returns a variable object based on the specified
* ExpressionDMC, creating it in GDB if it was not created already.
@ -1354,7 +1418,7 @@ public class MIVariableManager implements ICommandControl {
final DataRequestMonitor<MIVariableObject> rm) {
// Generate an id for this expression so that we can determine if we already
// have a variable object tracking it. If we don't we'll need to create one.
final VariableObjectId id = new VariableObjectId();
final VariableObjectId id = createVariableObjectId();
id.generateId(
exprCtx,
new RequestMonitor(fSession.getExecutor(), rm) {
@ -1431,7 +1495,7 @@ public class MIVariableManager implements ICommandControl {
// Variable objects that are created directly like this, are considered ROOT variable objects
// in comparison to variable objects that are children of other variable objects.
final MIRootVariableObject newVarObj = new MIRootVariableObject(id);
final MIRootVariableObject newVarObj = createRootVariableObject(id);
// We must put this object in our map right away, in case it is
// requested again, before it completes its creation.
@ -1443,7 +1507,7 @@ public class MIVariableManager implements ICommandControl {
protected void handleCompleted() {
if (isSuccess()) {
// Also store the object as a varObj that is up-to-date
updatedRootList.add(newVarObj);
rootVariableUpdated(newVarObj);
// VarObj can now be used by others
newVarObj.creationCompleted(true);
@ -1625,7 +1689,7 @@ public class MIVariableManager implements ICommandControl {
}
});
} else if (command instanceof MIDataEvaluateExpression) {
} else if (command instanceof MIDataEvaluateExpression<?>) {
// This does not use the variable objects but sends the command directly to the back-end
fCommandControl.queueCommand(command, rm);
} else {
@ -1684,7 +1748,7 @@ public class MIVariableManager implements ICommandControl {
public void markAllOutOfDate() {
MIRootVariableObject root;
while ((root = updatedRootList.poll()) != null) {
root.markAsOutOfDate();
root.setOutOfDate(true);
}
}

View file

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of frame contexts
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands.macos;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.macos.MacOSMIVarUpdateInfo;
/**
*
* -var-update [print-values] {NAME | "*"}
*
* Update the value of the variable object NAME by evaluating its
* expression after fetching all the new values from memory or registers.
* A `*' causes all existing variable objects to be updated.
* If print-values has a value for of 0 or --no-values, print only the names of the variables;
* if print-values is 1 or --all-values, also print their values;
* if it is 2 or --simple-values print the name and value for simple data types and just
* the name for arrays, structures and unions.
*
* It seems that for MacOS, we must use the full string for print-values, such as
* --all-values.
*
* @since 2.1
*/
public class MacOSMIVarUpdate extends MICommand<MacOSMIVarUpdateInfo> {
public MacOSMIVarUpdate(ICommandControlDMContext dmc, String name) {
// Must use --all-values instead of 1 for Mac OS
super(dmc, "-var-update", new String[] { "--all-values", name }); //$NON-NLS-1$//$NON-NLS-2$
}
@Override
public MacOSMIVarUpdateInfo getResult(MIOutput out) {
return new MacOSMIVarUpdateInfo(out);
}
}

View file

@ -0,0 +1,123 @@
/*******************************************************************************
* Copyright (c) 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
* Ericsson - Created version for Mac OS
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output.macos;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIList;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MITuple;
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarChange;
/**
* GDB/MI var-update for Mac OS.
* -var-update *
* ^done,changelist=[varobj={name="var1",in_scope="true",type_changed="false"}],time={.....}
*
* @since 2.1
*/
public class MacOSMIVarUpdateInfo extends MIInfo {
MIVarChange[] changeList;
public MacOSMIVarUpdateInfo(MIOutput record) {
super(record);
List<MIVarChange> aList = new ArrayList<MIVarChange>();
if (isDone()) {
MIOutput out = getMIOutput();
MIResultRecord rr = out.getMIResultRecord();
if (rr != null) {
MIResult[] results = rr.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("changelist")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue();
if (value instanceof MITuple) {
parseChangeList((MITuple)value, aList);
} else if (value instanceof MIList) {
parseChangeList((MIList)value, aList);
}
}
}
}
}
changeList = aList.toArray(new MIVarChange[aList.size()]);
}
public MIVarChange[] getMIVarChanges() {
return changeList;
}
/**
* For MI2 the format is now a MIList.
* @param tuple
* @param aList
*/
void parseChangeList(MIList miList, List<MIVarChange> aList) {
// The MIList in Apple gdb contains MIResults instead of MIValues. It looks like:
// ^done,changelist=[varobj={name="var1",in_scope="true",type_changed="false"}],time={.....}
// Bug 250037
MIResult[] results = miList.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("varobj")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue();
if (value instanceof MITuple) {
parseChangeList((MITuple)value, aList);
} else if (value instanceof MIList) {
parseChangeList((MIList)value, aList);
}
}
}
}
void parseChangeList(MITuple tuple, List<MIVarChange> aList) {
MIResult[] results = tuple.getMIResults();
MIVarChange change = null;
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
if (value instanceof MITuple) {
parseChangeList((MITuple)value, aList);
}
else
{
String str = ""; //$NON-NLS-1$
if (value instanceof MIConst) {
str = ((MIConst)value).getString();
}
if (var.equals("name")) { //$NON-NLS-1$
change = new MIVarChange(str);
aList.add(change);
} else if (var.equals("value")) { //$NON-NLS-1$
if (change != null) {
change.setValue(str);
}
} else if (var.equals("in_scope")) { //$NON-NLS-1$
if (change != null) {
change.setInScope("true".equals(str)); //$NON-NLS-1$
}
} else if (var.equals("type_changed")) { //$NON-NLS-1$
if (change != null) {
change.setChanged("true".equals(str)); //$NON-NLS-1$
}
}
}
}
}
}