diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java index 3fc8e56c2a5..e676e65198a 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java @@ -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); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java index 4a8438c1cea..7b6167f3141 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java @@ -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; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBExpressions.java new file mode 100644 index 00000000000..33e002f73d9 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBExpressions.java @@ -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()); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBVariableManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBVariableManager.java new file mode 100644 index 00000000000..e76de9d3618 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBVariableManager.java @@ -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 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(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 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 pendingRm = updatesPending.poll(); + pendingRm.setStatus(getStatus()); + pendingRm.done(); + } + } + } + }); + } + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGdbDebugServicesFactory.java new file mode 100644 index 00000000000..348c3d8d42d --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGdbDebugServicesFactory.java @@ -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); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java index 6bc32069c06..445b1cd5c6e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java @@ -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 diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java index 30964322106..79031ac7c32 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java @@ -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 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 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); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/macos/MacOSMIVarUpdate.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/macos/MacOSMIVarUpdate.java new file mode 100644 index 00000000000..8a0326836f8 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/macos/MacOSMIVarUpdate.java @@ -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 { + + 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); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/macos/MacOSMIVarUpdateInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/macos/MacOSMIVarUpdateInfo.java new file mode 100644 index 00000000000..a983fb9f455 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/macos/MacOSMIVarUpdateInfo.java @@ -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 aList = new ArrayList(); + 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 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 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$ + } + } + } + } + } +}