Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlvaro Sanchez-Leon2014-10-24 11:42:04 -0400
committerAlvaro Sanchez-Leon2014-12-09 10:37:26 -0500
commit3ab1678bc370c56cb41f6830a872e806555ef61a (patch)
tree18157c35fbde11d23a71f0947d8dd8ced5337caf
parenta830f285fe92a58fb9689020c3ddc605b0d36867 (diff)
downloadorg.eclipse.cdt-3ab1678bc370c56cb41f6830a872e806555ef61a.tar.gz
org.eclipse.cdt-3ab1678bc370c56cb41f6830a872e806555ef61a.tar.xz
org.eclipse.cdt-3ab1678bc370c56cb41f6830a872e806555ef61a.zip
Bug 235747: [registers] Allow user to edit the register groups.
Bug 235747: Move register group actions to the command framework. Change-Id: Ife5aefc1a1609309724db01d92a35750e25def24 Signed-off-by: Alvaro Sanchez-Leon <alvsan09@gmail.com> Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com> Reviewed-on: https://git.eclipse.org/r/13980 Tested-by: Hudson CI
-rw-r--r--debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF20
-rw-r--r--debug/org.eclipse.cdt.debug.core/pom.xml2
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IAddRegisterGroupHandler.java21
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IEditRegisterGroupHandler.java21
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRemoveRegisterGroupsHandler.java20
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRestoreRegisterGroupsHandler.java20
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java263
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java35
-rw-r--r--debug/org.eclipse.cdt.debug.ui/plugin.properties18
-rw-r--r--debug/org.eclipse.cdt.debug.ui/plugin.xml198
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AbstractViewActionDelegate.java4
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/ActionMessages.properties4
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AddRegisterGroupActionDelegate.java91
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/EditRegisterGroupActionDelegate.java82
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RemoveRegisterGroupActionDelegate.java87
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RestoreDefaultRegisterGroupsActionDelegate.java70
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AbstractRegisterGroupCommandHandler.java169
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AddRegisterGroupCommandHandler.java45
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/EditRegisterGroupCommandHandler.java45
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RemoveRegisterGroupsCommandHandler.java45
-rw-r--r--debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RestoreRegisterGroupsCommandHandler.java45
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBPatternMatchingExpressions.java62
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java1137
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java4
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java6
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties6
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java176
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.java5
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.properties7
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java39
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/GDBPatternMatchingExpressionsTest.java58
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java1496
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/plugin.xml66
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java11
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties12
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/AbstractDsfRegisterGroupActions.java1010
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfAddRegisterGroupCommand.java48
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfEditRegisterGroupCommand.java48
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRemoveRegisterGroupsCommand.java48
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRestoreRegisterGroupsCommand.java48
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java19
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRegisters2.java90
42 files changed, 4761 insertions, 940 deletions
diff --git a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
index a2bfcf6e17..c1a8700f16 100644
--- a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
+++ b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.debug.core; singleton:=true
-Bundle-Version: 7.5.0.qualifier
+Bundle-Version: 7.6.0.qualifier
Bundle-Activator: org.eclipse.cdt.debug.core.CDebugCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -16,20 +16,28 @@ Export-Package: org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.core.disassembly,
org.eclipse.cdt.debug.core.executables,
org.eclipse.cdt.debug.core.model,
- org.eclipse.cdt.debug.core.model.provisional;x-friends:="org.eclipse.cdt.dsf,org.eclipse.cdt.debug.ui.memory.memorybrowser,org.eclipse.cdt.dsf.gdb,org.eclipse.cdt.debug.ui.memory.traditional",
+ org.eclipse.cdt.debug.core.model.provisional;
+ x-friends:="org.eclipse.cdt.dsf,
+ org.eclipse.cdt.debug.ui.memory.memorybrowser,
+ org.eclipse.cdt.dsf.gdb,
+ org.eclipse.cdt.debug.ui.memory.traditional",
org.eclipse.cdt.debug.core.sourcelookup,
- org.eclipse.cdt.debug.internal.core;x-friends:="org.eclipse.cdt.dsf.gdb,org.eclipse.cdt.dsf.gdb.ui,org.eclipse.cdt.dsf,org.eclipse.cdt.dsf.ui",
+ org.eclipse.cdt.debug.internal.core;
+ x-friends:="org.eclipse.cdt.dsf.gdb,
+ org.eclipse.cdt.dsf.gdb.ui,
+ org.eclipse.cdt.dsf,
+ org.eclipse.cdt.dsf.ui",
org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc,org.eclipse.cdt.dsf.gdb",
org.eclipse.cdt.debug.internal.core.disassembly;x-internal:=true,
org.eclipse.cdt.debug.internal.core.executables;x-internal:=true,
- org.eclipse.cdt.debug.internal.core.model;x-internal:=true,
- org.eclipse.cdt.debug.internal.core.srcfinder;x-internal:=true,
+ org.eclipse.cdt.debug.internal.core.model;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.dsf.gdb",
org.eclipse.cdt.debug.internal.core.sourcelookup;
x-friends:="org.eclipse.cdt.dsf.ui,
org.eclipse.cdt.debug.edc,
org.eclipse.cdt.debug.gdbjtag.core,
org.eclipse.cdt.dsf.gdb,
- org.eclipse.cdt.dsf"
+ org.eclipse.cdt.dsf",
+ org.eclipse.cdt.debug.internal.core.srcfinder;x-internal:=true
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
org.eclipse.cdt.core;bundle-version="[5.0.0,6.0.0)",
diff --git a/debug/org.eclipse.cdt.debug.core/pom.xml b/debug/org.eclipse.cdt.debug.core/pom.xml
index 9de6ccb176..bc8d0d3dad 100644
--- a/debug/org.eclipse.cdt.debug.core/pom.xml
+++ b/debug/org.eclipse.cdt.debug.core/pom.xml
@@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
- <version>7.5.0-SNAPSHOT</version>
+ <version>7.6.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.debug.core</artifactId>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IAddRegisterGroupHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IAddRegisterGroupHandler.java
new file mode 100644
index 0000000000..1e402ad491
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IAddRegisterGroupHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.core.model;
+
+import org.eclipse.debug.core.commands.IDebugCommandHandler;
+
+/**
+ * Handler interface to for the addRegisterGroup command
+ *
+ * @since 7.6
+ */
+public interface IAddRegisterGroupHandler extends IDebugCommandHandler {
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IEditRegisterGroupHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IEditRegisterGroupHandler.java
new file mode 100644
index 0000000000..721c7e2eec
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IEditRegisterGroupHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.core.model;
+
+import org.eclipse.debug.core.commands.IDebugCommandHandler;
+
+/**
+ * Handler interface to for the editRegisterGroup command
+ * @since 7.6
+ */
+public interface IEditRegisterGroupHandler extends IDebugCommandHandler {
+}
+
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRemoveRegisterGroupsHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRemoveRegisterGroupsHandler.java
new file mode 100644
index 0000000000..b8c77e9a98
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRemoveRegisterGroupsHandler.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.core.model;
+
+import org.eclipse.debug.core.commands.IDebugCommandHandler;
+
+/**
+ * Handler interface to for the removeRegisterGroups command
+ * @since 7.6
+ */
+public interface IRemoveRegisterGroupsHandler extends IDebugCommandHandler {
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRestoreRegisterGroupsHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRestoreRegisterGroupsHandler.java
new file mode 100644
index 0000000000..56d9ef748a
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IRestoreRegisterGroupsHandler.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.core.model;
+
+import org.eclipse.debug.core.commands.IDebugCommandHandler;
+
+/**
+ * Handler interface to for the restoreRegisterGroups command
+ * @since 7.6
+ */
+public interface IRestoreRegisterGroupsHandler extends IDebugCommandHandler {
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java
new file mode 100644
index 0000000000..2a811c7b9a
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2014 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 in CRegisterManager.java and CRegisterGroup.java
+ * Alvaro Sanchez-Leon (Ericsson) - Integrated from files above for Bug 235747
+ *******************************************************************************/
+
+package org.eclipse.cdt.debug.internal.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
+import org.eclipse.cdt.debug.internal.core.model.CoreModelMessages;
+import org.eclipse.cdt.debug.internal.core.model.IRegisterGroupDescriptor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class RegisterGroupsPersistance {
+ private static final String BLANK_STRING = ""; //$NON-NLS-1$
+ private static final String DEFAULT_LAUNCH_CONFIGURATION_TARGET_ATTRIBUTE = ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_REGISTER_GROUPS;
+ private static final String ELEMENT_REGISTER_GROUP_LIST = "registerGroups"; //$NON-NLS-1$
+ private static final String ATTR_REGISTER_GROUP_MEMENTO = "memento"; //$NON-NLS-1$
+
+ private static final String ELEMENT_GROUP = "group"; //$NON-NLS-1$
+ private static final String ELEMENT_REGISTER_GROUP = "registerGroup"; //$NON-NLS-1$
+ private static final String ATTR_REGISTER_GROUP_NAME = "name"; //$NON-NLS-1$
+ private static final String ATTR_REGISTER_GROUP_ENABLED = "enabled"; //$NON-NLS-1$
+
+ private static final String ELEMENT_REGISTER = "register"; //$NON-NLS-1$
+
+ private static final String ATTR_REGISTER_NAME = "name"; //$NON-NLS-1$
+ private static final String ATTR_REGISTER_ORIGINAL_GROUP_NAME = "originalGroupName"; //$NON-NLS-1$
+
+ private final ILaunchConfiguration fLaunchConfig;
+
+ private String fLaunchConfigTargetAttribute = DEFAULT_LAUNCH_CONFIGURATION_TARGET_ATTRIBUTE;
+
+ // Constructor
+ public RegisterGroupsPersistance(ILaunchConfiguration configuration) {
+ fLaunchConfig = configuration;
+ }
+
+ private class RegisterGroupDescriptor implements IRegisterGroupDescriptor {
+
+ private final String fMemento;
+ private final String fName;
+ private final boolean fEnabled;
+ IRegisterDescriptor[] fRegisterDescriptors = null;
+
+ public RegisterGroupDescriptor(String memento, String groupName, boolean enabled) {
+ fMemento = memento;
+ fName = groupName;
+ fEnabled = enabled;
+ }
+
+ @Override
+ public String getName() {
+ return fName;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return fEnabled;
+ }
+
+ @Override
+ public IRegisterDescriptor[] getChildren() throws CoreException {
+ if (fRegisterDescriptors == null) {
+
+ Node node = DebugPlugin.parseDocument(fMemento);
+ Element element = (Element) node;
+
+ List<IRegisterDescriptor> list = new ArrayList<IRegisterDescriptor>();
+ Node childNode = element.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element child = (Element) childNode;
+ if (ELEMENT_REGISTER.equals(child.getNodeName())) {
+ String name = child.getAttribute(ATTR_REGISTER_NAME);
+ String originalGroupName = child.getAttribute(ATTR_REGISTER_ORIGINAL_GROUP_NAME);
+ if (name == null || name.length() == 0 || originalGroupName == null
+ || originalGroupName.length() == 0) {
+ abort(CoreModelMessages.getString("CRegisterGroup.3"), null); //$NON-NLS-1$
+ } else {
+ IRegisterDescriptor d = findDescriptor(originalGroupName, name);
+ if (d != null)
+ list.add(d);
+ else
+ CDebugCorePlugin.log(CoreModelMessages.getString("CRegisterGroup.4")); //$NON-NLS-1$
+ }
+ }
+ }
+ childNode = childNode.getNextSibling();
+ }
+
+ fRegisterDescriptors = list.toArray(new IRegisterDescriptor[list.size()]);
+ }
+
+ return fRegisterDescriptors;
+ }
+
+ }
+
+ class RegisterDescriptor implements IRegisterDescriptor {
+ private final String fGroupName;
+ private final String fName;
+
+ private RegisterDescriptor(String oGroupName, String rname) {
+ fGroupName = oGroupName;
+ fName = rname;
+ }
+
+ @Override
+ public String getName() {
+ return fName;
+ }
+
+ @Override
+ public String getGroupName() {
+ return fGroupName;
+ }
+ }
+
+ public void setLaunchConfigurationTargetAttribute(String launchConfigurationTargetAttribute) {
+ fLaunchConfigTargetAttribute = launchConfigurationTargetAttribute;
+ }
+
+ public String getLaunchConfigurationTargetAttribute() {
+
+ return fLaunchConfigTargetAttribute;
+ }
+
+ public IRegisterGroupDescriptor[] parseGroups() {
+ List<IRegisterGroupDescriptor> groups = new ArrayList<IRegisterGroupDescriptor>();
+ String memento;
+ try {
+ memento = fLaunchConfig.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_REGISTER_GROUPS, BLANK_STRING);
+
+ if (memento != null && memento.length() > 0) {
+ Node node = DebugPlugin.parseDocument(memento);
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ abort("Unable to restore register groups - invalid memento.", null); //$NON-NLS-1$
+ }
+ Element element = (Element) node;
+ if (!ELEMENT_REGISTER_GROUP_LIST.equals(element.getNodeName())) {
+ abort("Unable to restore register groups - expecting register group list element.", null); //$NON-NLS-1$
+ }
+
+ Node childNode = element.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element child = (Element) childNode;
+ if (ELEMENT_GROUP.equals(child.getNodeName())) {
+ String groupMemento = child.getAttribute(ATTR_REGISTER_GROUP_MEMENTO);
+ //
+ IRegisterGroupDescriptor groupdesc = createGroupFromMemento(groupMemento);
+ if (groupdesc != null) {
+ groups.add(groupdesc);
+ }
+ }
+ }
+ childNode = childNode.getNextSibling();
+ }
+
+ }
+ } catch (CoreException e) {
+
+ e.printStackTrace();
+ }
+
+ return groups.toArray(new IRegisterGroupDescriptor[groups.size()]);
+
+ }
+
+ public void saveGroups(IRegisterGroupDescriptor[] groups) throws CoreException {
+ try {
+ ILaunchConfigurationWorkingCopy wc = fLaunchConfig.getWorkingCopy();
+
+ //if no groups present, save to a blank string, i.e. expected by CDI and handled by DSF
+ wc.setAttribute(fLaunchConfigTargetAttribute, (groups.length > 0) ? getMemento(groups) : BLANK_STRING);
+ wc.doSave();
+ } catch (CoreException e) {
+ abort(e.getMessage() + ", cause: " + e.getCause(), e); //$NON-NLS-1$
+ }
+ }
+
+ protected IRegisterDescriptor findDescriptor(String originalGroupName, String name) {
+ return new RegisterDescriptor(originalGroupName, name);
+ }
+
+ private IRegisterGroupDescriptor createGroupFromMemento(String memento) throws CoreException {
+ Node node = DebugPlugin.parseDocument(memento);
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ abort(CoreModelMessages.getString("CRegisterGroup.0"), null); //$NON-NLS-1$
+ }
+ Element element = (Element) node;
+ if (!ELEMENT_REGISTER_GROUP.equals(element.getNodeName())) {
+ abort(CoreModelMessages.getString("CRegisterGroup.1"), null); //$NON-NLS-1$
+ }
+ String groupName = element.getAttribute(ATTR_REGISTER_GROUP_NAME);
+ if (groupName == null || groupName.length() == 0) {
+ abort(CoreModelMessages.getString("CRegisterGroup.2"), null); //$NON-NLS-1$
+ }
+ String e = element.getAttribute(ATTR_REGISTER_GROUP_ENABLED);
+ boolean enabled = Boolean.parseBoolean(e);
+
+ IRegisterGroupDescriptor group = new RegisterGroupDescriptor(memento, groupName, enabled);
+
+ return group;
+ }
+
+ private String getMemento(IRegisterGroupDescriptor[] groups) throws CoreException {
+ Document document = DebugPlugin.newDocument();
+ Element element = document.createElement(ELEMENT_REGISTER_GROUP_LIST);
+ for (IRegisterGroupDescriptor group : groups) {
+ Element child = document.createElement(ELEMENT_GROUP);
+ child.setAttribute(ATTR_REGISTER_GROUP_MEMENTO, getMemento(group));
+ element.appendChild(child);
+ }
+
+ document.appendChild(element);
+ return DebugPlugin.serializeDocument(document);
+ }
+
+ private String getMemento(IRegisterGroupDescriptor group) throws CoreException {
+ Document document = DebugPlugin.newDocument();
+ Element element = document.createElement(ELEMENT_REGISTER_GROUP);
+ element.setAttribute(ATTR_REGISTER_GROUP_NAME, group.getName());
+ element.setAttribute(ATTR_REGISTER_GROUP_ENABLED, Boolean.valueOf(group.isEnabled()).toString());
+ IRegisterDescriptor[] registerDescriptors = group.getChildren();
+ for (int i = 0; i < registerDescriptors.length; ++i) {
+ Element child = document.createElement(ELEMENT_REGISTER);
+ child.setAttribute(ATTR_REGISTER_NAME, registerDescriptors[i].getName());
+ child.setAttribute(ATTR_REGISTER_ORIGINAL_GROUP_NAME, registerDescriptors[i].getGroupName());
+ element.appendChild(child);
+ }
+
+ document.appendChild(element);
+ return DebugPlugin.serializeDocument(document);
+ }
+
+ private void abort(String message, Throwable exception) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR, CDebugCorePlugin.PLUGIN_ID, IStatus.ERROR, message, exception);
+ throw new CoreException(status);
+ }
+
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java
new file mode 100644
index 0000000000..ff72c97a26
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson AB 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:
+ * Alvaro Sanchez-Leon (Ericsson) - First Implementation and API (Bug 235747)
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core.model;
+
+import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * Describes a register Group
+ */
+public interface IRegisterGroupDescriptor {
+ /**
+ * @return the register group's name
+ */
+ public String getName();
+
+ /**
+ * @return the enabled state
+ */
+ public boolean isEnabled();
+
+ /**
+ * @return the registers associated to this group
+ * @throws CoreException
+ */
+ public IRegisterDescriptor[] getChildren() throws CoreException;
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.properties b/debug/org.eclipse.cdt.debug.ui/plugin.properties
index 2fda45869f..3daa217a7d 100644
--- a/debug/org.eclipse.cdt.debug.ui/plugin.properties
+++ b/debug/org.eclipse.cdt.debug.ui/plugin.properties
@@ -142,12 +142,26 @@ ModulesDetailPaneFontDefinition.description=The text font used in the detail pan
ModulePropertiesAction.label=Properties...
ModulePropertiesAction.tooltip=Open Module Properties Dialog
+RegisterGroupingCategory.description=Set of commands for Register Grouping
+RegisterGroupingCategory.name=Register Grouping commands
+AddRegisterGroup.description=Adds a Register Group
+AddRegisterGroup.name=Add RegisterGroup
+AddRegisterGroup.label=Add Register Group
AddRegisterGroupAction.label=Add Register Group
AddRegisterGroupAction.tooltip=Add Register Group
-RemoveRegisterGroupAction.label=Remove Register Group
-RemoveRegisterGroupAction.tooltip=Remove Register Group
+RemoveRegisterGroups.description=Removes one or more Register Groups
+RemoveRegisterGroups.name=Remove Register Groups
+RemoveRegisterGroups.label=Remove Register Groups
+RemoveRegisterGroupsAction.label=Remove Register Groups
+RemoveRegisterGroupsAction.tooltip=Remove Register Groups
+EditRegisterGroup.description=Edits a Register Group
+EditRegisterGroup.name=Edit Register Group
+EditRegisterGroup.label=Edit Register Group
EditRegisterGroupAction.label=Edit Register Group
EditRegisterGroupAction.tooltip=Edit Register Group
+RestoreRegisterGroups.description=Restores the Default Register Groups
+RestoreRegisterGroups.name=Restore Default Register Groups
+RestoreRegisterGroups.label=Restore Default Register Groups
RestoredefaultRegisterGroupsAction.label=Restore Default Register Groups
RestoredefaultRegisterGroupsAction.tooltip=Restore Default Register Groups
diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml
index ac39c56751..0b58b5245e 100644
--- a/debug/org.eclipse.cdt.debug.ui/plugin.xml
+++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml
@@ -798,34 +798,6 @@
class="org.eclipse.cdt.debug.core.model.ICVariable">
</selection>
</action>
- <action
- class="org.eclipse.cdt.debug.internal.ui.actions.RestoreDefaultRegisterGroupsActionDelegate"
- helpContextId="restore_default_register_groups_action_context"
- id="org.eclipse.cdt.debug.ui.restoreDefaultRegisterGroupsAction"
- label="%RestoredefaultRegisterGroupsAction.label"
- menubarPath="additions"
- style="push"
- tooltip="%RestoredefaultRegisterGroupsAction.tooltip">
- <enablement>
- <pluginState
- id="org.eclipse.cdt.debug.ui"
- value="activated"/>
- </enablement>
- </action>
- <action
- class="org.eclipse.cdt.debug.internal.ui.actions.AddRegisterGroupActionDelegate"
- helpContextId="add_register_group_action_context"
- id="org.eclipse.cdt.debug.ui.addRegisterGroupAction"
- label="%AddRegisterGroupAction.label"
- menubarPath="additions"
- style="push"
- tooltip="%AddRegisterGroupAction.tooltip">
- <enablement>
- <pluginState
- id="org.eclipse.cdt.debug.ui"
- value="activated"/>
- </enablement>
- </action>
</viewerContribution>
<objectContribution
objectClass="org.eclipse.cdt.debug.core.model.ICModule"
@@ -868,27 +840,6 @@
</enablement>
</action>
</viewerContribution>
- <objectContribution
- adaptable="false"
- id="org.eclipse.cdt.debug.ui.RegisterGroupActions"
- objectClass="org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup">
- <action
- class="org.eclipse.cdt.debug.internal.ui.actions.RemoveRegisterGroupActionDelegate"
- enablesFor="+"
- helpContextId="remove_register_group_action_context"
- id="org.eclipse.cdt.debug.ui.removeRegisterGroupAction"
- label="%RemoveRegisterGroupAction.label"
- menubarPath="additions"
- tooltip="%RemoveRegisterGroupAction.tooltip"/>
- <action
- class="org.eclipse.cdt.debug.internal.ui.actions.EditRegisterGroupActionDelegate"
- enablesFor="1"
- helpContextId="edit_register_group_action_context"
- id="org.eclipse.cdt.debug.ui.editRegisterGroupAction"
- label="%EditRegisterGroupAction.label"
- menubarPath="additions"
- tooltip="%EditRegisterGroupAction.tooltip"/>
- </objectContribution>
<viewerContribution
id="org.eclipse.debug.ui.MemoryView.RenderingViewPane.popupMenu.1"
targetID="org.eclipse.debug.ui.MemoryView.RenderingViewPane.1">
@@ -1395,18 +1346,14 @@
<factory
class="org.eclipse.cdt.debug.internal.ui.actions.RetargettableActionAdapterFactory"
adaptableType="org.eclipse.cdt.internal.ui.editor.CEditor">
- <adapter
- type="org.eclipse.debug.ui.actions.IRunToLineTarget">
- </adapter>
+ <adapter type="org.eclipse.debug.ui.actions.IRunToLineTarget"/>
<adapter type="org.eclipse.cdt.debug.internal.ui.actions.IResumeAtLineTarget"/>
<adapter type="org.eclipse.cdt.debug.internal.ui.actions.IMoveToLineTarget"/>
</factory>
<factory
class="org.eclipse.cdt.debug.internal.ui.actions.RetargettableActionAdapterFactory"
adaptableType="org.eclipse.cdt.internal.ui.editor.asm.AsmTextEditor">
- <adapter
- type="org.eclipse.debug.ui.actions.IRunToLineTarget">
- </adapter>
+ <adapter type="org.eclipse.debug.ui.actions.IRunToLineTarget"/>
<adapter type="org.eclipse.cdt.debug.internal.ui.actions.IResumeAtLineTarget"/>
<adapter type="org.eclipse.cdt.debug.internal.ui.actions.IMoveToLineTarget"/>
</factory>
@@ -1965,6 +1912,35 @@
<extension
point="org.eclipse.ui.commands">
<category
+ description="%RegisterGroupingCategory.description"
+ id="org.eclipse.cdt.debug.ui.category.registerGrouping"
+ name="%RegisterGroupingCategory.name">
+ </category>
+ <command
+ categoryId="org.eclipse.cdt.debug.ui.category.registerGrouping"
+ description="%AddRegisterGroup.description"
+ id="org.eclipse.cdt.debug.ui.command.addRegisterGroup"
+ name="%AddRegisterGroup.name">
+ </command>
+ <command
+ categoryId="org.eclipse.cdt.debug.ui.category.registerGrouping"
+ description="%EditRegisterGroup.description"
+ id="org.eclipse.cdt.debug.ui.command.editRegisterGroup"
+ name="%EditRegisterGroup.name">
+ </command>
+ <command
+ categoryId="org.eclipse.cdt.debug.ui.category.registerGrouping"
+ description="%RestoreRegisterGroups.description"
+ id="org.eclipse.cdt.debug.ui.command.restoreRegisterGroups"
+ name="%RestoreRegisterGroups.name">
+ </command>
+ <command
+ categoryId="org.eclipse.cdt.debug.ui.category.registerGrouping"
+ description="%RemoveRegisterGroups.description"
+ id="org.eclipse.cdt.debug.ui.command.removeRegisterGroups"
+ name="%RemoveRegisterGroups.name">
+ </command>
+ <category
description="%ReverseDebuggingCategory.description"
id="org.eclipse.cdt.debug.ui.category.reverseDebugging"
name="%ReverseDebuggingCategory.name">
@@ -2073,6 +2049,76 @@
<extension
point="org.eclipse.ui.handlers">
<handler
+ class="org.eclipse.cdt.debug.internal.ui.commands.AddRegisterGroupCommandHandler"
+ commandId="org.eclipse.cdt.debug.ui.command.addRegisterGroup">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <or>
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegisterGroup">
+ </instanceof>
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegister">
+ </instanceof>
+ </or>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.debug.internal.ui.commands.EditRegisterGroupCommandHandler"
+ commandId="org.eclipse.cdt.debug.ui.command.editRegisterGroup">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegisterGroup">
+ </instanceof>
+ </iterate>
+ <count value="1">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.debug.internal.ui.commands.RestoreRegisterGroupsCommandHandler"
+ commandId="org.eclipse.cdt.debug.ui.command.restoreRegisterGroups">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <or>
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegisterGroup">
+ </instanceof>
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegister">
+ </instanceof>
+ </or>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.debug.internal.ui.commands.RemoveRegisterGroupsCommandHandler"
+ commandId="org.eclipse.cdt.debug.ui.command.removeRegisterGroups">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <instanceof
+ value="org.eclipse.cdt.debug.internal.core.model.CRegisterGroup">
+ </instanceof>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
class="org.eclipse.cdt.debug.internal.ui.commands.ReverseToggleCommandHandler"
commandId="org.eclipse.cdt.debug.ui.command.reverseToggle">
</handler>
@@ -2279,6 +2325,48 @@
<extension
point="org.eclipse.ui.menus">
+<!-- Register Grouping contributions to the registers view popup -->
+ <menuContribution
+ locationURI="popup:org.eclipse.debug.ui.RegisterView?after=additions">
+ <command
+ commandId="org.eclipse.cdt.debug.ui.command.restoreRegisterGroups"
+ label="%RestoreRegisterGroups.label"
+ style="push">
+ <visibleWhen checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.debug.ui.RegisterView?after=additions">
+ <command
+ commandId="org.eclipse.cdt.debug.ui.command.addRegisterGroup"
+ label="%AddRegisterGroup.label"
+ style="push">
+ <visibleWhen checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.debug.ui.RegisterView?after=additions">
+ <command
+ commandId="org.eclipse.cdt.debug.ui.command.removeRegisterGroups"
+ label="%RemoveRegisterGroups.label"
+ style="push">
+ <visibleWhen checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.debug.ui.RegisterView?after=additions">
+ <command
+ commandId="org.eclipse.cdt.debug.ui.command.editRegisterGroup"
+ label="%EditRegisterGroup.label"
+ style="push">
+ <visibleWhen checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </menuContribution>
+
<!-- Reverse debugging contributions to Debug view -->
<menuContribution
locationURI="toolbar:org.eclipse.debug.ui.DebugView?after=additions">
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AbstractViewActionDelegate.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AbstractViewActionDelegate.java
index e64b23b7fc..e15e789278 100644
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AbstractViewActionDelegate.java
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AbstractViewActionDelegate.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2007 QNX Software Systems and others.
+ * Copyright (c) 2004, 2014 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
@@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - preserve selection changes (needed by Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.ui.actions;
@@ -187,6 +188,7 @@ public abstract class AbstractViewActionDelegate extends ActionDelegate implemen
*/
@Override
public void selectionChanged( IAction action, ISelection selection ) {
+ setSelection( selection );
update();
}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/ActionMessages.properties b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/ActionMessages.properties
index db038c6df1..c2060af77c 100644
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/ActionMessages.properties
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/ActionMessages.properties
@@ -11,6 +11,7 @@
# Marc Khouzam (Ericsson) - Added dynamic printf support (400628)
# Simon Marchi (Ericsson) - Modified error messages in CastToArrayActionDelegate (437182)
# Marc Dumais (Ericsson) - Bug 437692
+# Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
###############################################################################
LoadSymbolsActionDelegate.Unable_to_load_symbols_of_shared_library_1=Unable to load symbols of shared library.
@@ -119,9 +120,10 @@ ToggleDetailPaneAction.4=Place the Detail Pane on the Right of the Main Tree Vie
ToggleDetailPaneAction.5=Place the Detail Pane on the Right of the Main Tree View
ToggleDetailPaneAction.6=Hide the Detail Pane so that only the Main Tree View is Visible
ToggleDetailPaneAction.7=Hide the Detail Pane so that only the Main Tree View is Visible
-AddRegisterGroupActionDelegate.0=Error
+RegisterGroupActionDelegate.0=Error
AddRegisterGroupActionDelegate.1=Error(s) occurred adding register group.
EditRegisterGroupActionDelegate.0=Unable to edit register group.
+RemoveRegisterGroupsActionDelegate.0=Unable to remove register group(s).
AddEventBreakpointActionDelegate.0=Error adding Event Breakpoint
AddEventBreakpointActionDelegate.2=Action is not supported by installed debuggers
ToggleCBreakpointsTargetFactory.CBreakpointDescription=Standard C/C++ breakpoint type.
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AddRegisterGroupActionDelegate.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AddRegisterGroupActionDelegate.java
deleted file mode 100644
index f673c7f09f..0000000000
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/AddRegisterGroupActionDelegate.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2005 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
- *******************************************************************************/
-package org.eclipse.cdt.debug.internal.ui.actions;
-
-import org.eclipse.cdt.debug.core.model.ICDebugTarget;
-import org.eclipse.debug.core.DebugEvent;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.model.IDebugElement;
-import org.eclipse.debug.ui.DebugUITools;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.window.Window;
-
-/**
- * A delegate for the "Add register group" action.
- */
-public class AddRegisterGroupActionDelegate extends AbstractViewActionDelegate {
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#getErrorDialogTitle()
- */
- @Override
- protected String getErrorDialogTitle() {
- return ActionMessages.getString( "AddRegisterGroupActionDelegate.0" ); //$NON-NLS-1$
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#getErrorDialogMessage()
- */
- @Override
- protected String getErrorDialogMessage() {
- return ActionMessages.getString( "AddRegisterGroupActionDelegate.1" ); //$NON-NLS-1$
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#doAction()
- */
- @Override
- protected void doAction() throws DebugException {
- RegisterGroupDialog dialog = new RegisterGroupDialog( getView().getSite().getShell(), getDebugTarget().getRegisterDescriptors() );
- if ( dialog.open() == Window.OK ) {
- getDebugTarget().addRegisterGroup( dialog.getName(), dialog.getDescriptors() );
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#update()
- */
- @Override
- protected void update() {
- IAction action = getAction();
- if ( action != null ) {
- ICDebugTarget target = getDebugTarget();
- action.setEnabled( ( target != null ) ? target.isSuspended() : false );
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#doHandleDebugEvent(org.eclipse.debug.core.DebugEvent)
- */
- @Override
- protected void doHandleDebugEvent( DebugEvent event ) {
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#init(org.eclipse.jface.action.IAction)
- */
- @Override
- public void init( IAction action ) {
- super.init( action );
- Object element = DebugUITools.getDebugContext();
- setSelection( (element != null) ? new StructuredSelection( element ) : new StructuredSelection() );
- update();
- }
-
- private ICDebugTarget getDebugTarget() {
- Object element = getSelection().getFirstElement();
- if ( element instanceof IDebugElement ) {
- return (ICDebugTarget)((IDebugElement)element).getDebugTarget().getAdapter( ICDebugTarget.class );
- }
- return null;
- }
-}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/EditRegisterGroupActionDelegate.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/EditRegisterGroupActionDelegate.java
deleted file mode 100644
index f1b27ff9ae..0000000000
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/EditRegisterGroupActionDelegate.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2005 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
- *******************************************************************************/
-package org.eclipse.cdt.debug.internal.ui.actions;
-
-import org.eclipse.cdt.debug.core.model.ICDebugTarget;
-import org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup;
-import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
-import org.eclipse.cdt.debug.internal.core.model.CDebugTarget;
-import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.model.IDebugTarget;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.actions.ActionDelegate;
-
-
-public class EditRegisterGroupActionDelegate extends ActionDelegate implements IObjectActionDelegate {
-
- private IPersistableRegisterGroup fSelection;
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
- */
- @Override
- public void setActivePart( IAction action, IWorkbenchPart targetPart ) {
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
- */
- @Override
- public void selectionChanged( IAction action, ISelection selection ) {
- if ( selection instanceof IStructuredSelection ) {
- IStructuredSelection ss = (IStructuredSelection)selection;
- if ( !ss.isEmpty() ) {
- Object s = ss.getFirstElement();
- if ( s instanceof IPersistableRegisterGroup ) {
- fSelection = (IPersistableRegisterGroup)s;
- }
- }
- }
- }
-
- private IPersistableRegisterGroup getRegisterGroup() {
- return fSelection;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
- */
- @Override
- public void run( IAction action ) {
- IPersistableRegisterGroup group = getRegisterGroup();
- IRegisterDescriptor[] all;
- try {
- all = ((CDebugTarget)group.getDebugTarget()).getRegisterDescriptors();
- RegisterGroupDialog dialog = new RegisterGroupDialog( Display.getCurrent().getActiveShell(), group.getName(), all, group.getRegisterDescriptors() );
- if ( dialog.open() == Window.OK ) {
- IDebugTarget target = group.getDebugTarget();
- if ( target instanceof ICDebugTarget ) {
- ((ICDebugTarget)target).modifyRegisterGroup( group, dialog.getDescriptors() );
- }
- }
- }
- catch( DebugException e ) {
- CDebugUIPlugin.errorDialog( ActionMessages.getString( "EditRegisterGroupActionDelegate.0" ), e.getStatus() ); //$NON-NLS-1$
- }
- }
-}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RemoveRegisterGroupActionDelegate.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RemoveRegisterGroupActionDelegate.java
deleted file mode 100644
index f35bddb93f..0000000000
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RemoveRegisterGroupActionDelegate.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2005 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
- *******************************************************************************/
-package org.eclipse.cdt.debug.internal.ui.actions;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import org.eclipse.cdt.debug.core.model.ICDebugTarget;
-import org.eclipse.debug.core.model.IDebugTarget;
-import org.eclipse.debug.core.model.IRegisterGroup;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.actions.ActionDelegate;
-
-/**
- * The "Remove Register Group" action.
- */
-public class RemoveRegisterGroupActionDelegate extends ActionDelegate implements IObjectActionDelegate {
-
- private IRegisterGroup[] fRegisterGroups;
-
- /**
- * Constructor for RemoveRegisterGroupActionDelegate.
- */
- public RemoveRegisterGroupActionDelegate() {
- super();
- setRegisterGroups( new IRegisterGroup[0] );
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
- */
- @Override
- public void setActivePart( IAction action, IWorkbenchPart targetPart ) {
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
- */
- @Override
- public void selectionChanged( IAction action, ISelection selection ) {
- ArrayList list = new ArrayList();
- if ( selection instanceof IStructuredSelection ) {
- IStructuredSelection ss = (IStructuredSelection)selection;
- Iterator it = ss.iterator();
- while( it.hasNext() ) {
- Object o = it.next();
- if ( o instanceof IRegisterGroup ) {
- list.add( o );
- }
- }
- }
- setRegisterGroups( (IRegisterGroup[])list.toArray( new IRegisterGroup[list.size()] ) );
- }
-
- protected IRegisterGroup[] getRegisterGroups() {
- return fRegisterGroups;
- }
-
- protected void setRegisterGroups( IRegisterGroup[] registerGroups ) {
- fRegisterGroups = registerGroups;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
- */
- @Override
- public void run( IAction action ) {
- IRegisterGroup[] groups = getRegisterGroups();
- if ( groups.length > 0 ) {
- IDebugTarget target = groups[0].getDebugTarget();
- if ( target instanceof ICDebugTarget ) {
- ((ICDebugTarget)target).removeRegisterGroups( groups );
- }
- }
- }
-}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RestoreDefaultRegisterGroupsActionDelegate.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RestoreDefaultRegisterGroupsActionDelegate.java
deleted file mode 100644
index 62dd536590..0000000000
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/RestoreDefaultRegisterGroupsActionDelegate.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2005 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
- *******************************************************************************/
-package org.eclipse.cdt.debug.internal.ui.actions;
-
-import org.eclipse.cdt.debug.core.model.ICDebugTarget;
-import org.eclipse.debug.core.DebugEvent;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.model.IDebugElement;
-import org.eclipse.debug.ui.DebugUITools;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.StructuredSelection;
-
-
-public class RestoreDefaultRegisterGroupsActionDelegate extends AbstractViewActionDelegate {
-
- @Override
- protected String getErrorDialogTitle() {
- return ActionMessages.getString( "RestoreDefaultRegisterGroupsActionDelegate.0" ); //$NON-NLS-1$
- }
-
- @Override
- protected String getErrorDialogMessage() {
- return ActionMessages.getString( "RestoreDefaultRegisterGroupsActionDelegate.1" ); //$NON-NLS-1$
- }
-
- @Override
- protected void doAction() throws DebugException {
- getDebugTarget().restoreDefaultRegisterGroups();
- }
-
- @Override
- protected void update() {
- IAction action = getAction();
- if ( action != null ) {
- ICDebugTarget target = getDebugTarget();
- action.setEnabled( ( target != null ) ? target.isSuspended() : false );
- }
- }
-
- @Override
- protected void doHandleDebugEvent( DebugEvent event ) {
- }
-
- private ICDebugTarget getDebugTarget() {
- Object element = getSelection().getFirstElement();
- if ( element instanceof IDebugElement ) {
- return (ICDebugTarget)((IDebugElement)element).getDebugTarget().getAdapter( ICDebugTarget.class );
- }
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.debug.internal.ui.actions.AbstractViewActionDelegate#init(org.eclipse.jface.action.IAction)
- */
- @Override
- public void init( IAction action ) {
- super.init( action );
- Object element = DebugUITools.getDebugContext();
- setSelection( (element != null) ? new StructuredSelection( element ) : new StructuredSelection() );
- update();
- }
-}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AbstractRegisterGroupCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AbstractRegisterGroupCommandHandler.java
new file mode 100644
index 0000000000..53629e7bb1
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AbstractRegisterGroupCommandHandler.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2014 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
+ * Alvaro Sanchez-Leon (Ericsson) - Support Register Groups (Bug 235747)
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.ui.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.cdt.debug.core.model.ICDebugTarget;
+import org.eclipse.cdt.debug.core.model.IPersistableRegisterGroup;
+import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
+import org.eclipse.cdt.debug.internal.core.model.CDebugTarget;
+import org.eclipse.cdt.debug.internal.ui.actions.ActionMessages;
+import org.eclipse.cdt.debug.internal.ui.actions.RegisterGroupDialog;
+import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+
+public abstract class AbstractRegisterGroupCommandHandler extends AbstractHandler {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#addRegisterGroup(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void addRegisterGroup(IStructuredSelection selection) {
+ ICDebugTarget t = getDebugTarget(selection);
+ if (t != null) {
+ // Using Debug model
+ try {
+ IRegisterDescriptor[] registers = t.getRegisterDescriptors();
+ RegisterGroupDialog dialog = new RegisterGroupDialog(Display.getCurrent().getActiveShell(), registers);
+ if (dialog.open() == Window.OK) {
+ t.addRegisterGroup(dialog.getName(), dialog.getDescriptors());
+ }
+ } catch (DebugException e) {
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canAddRegisterGroup(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public boolean canAddRegisterGroup(IStructuredSelection selection) {
+ ICDebugTarget target = getDebugTarget(selection);
+ return (target != null) ? target.isSuspended() : false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#editRegisterGroup(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void editRegisterGroup(IStructuredSelection selection) {
+ IPersistableRegisterGroup group = getRegisterGroup(selection);
+ if (group == null) {
+ return;
+ }
+
+ IRegisterDescriptor[] all;
+ try {
+ all = ((CDebugTarget) group.getDebugTarget()).getRegisterDescriptors();
+ RegisterGroupDialog dialog = new RegisterGroupDialog(Display.getCurrent().getActiveShell(),
+ group.getName(), all, group.getRegisterDescriptors());
+ if (dialog.open() == Window.OK) {
+ IDebugTarget target = group.getDebugTarget();
+ if (target instanceof ICDebugTarget) {
+ ((ICDebugTarget) target).modifyRegisterGroup(group, dialog.getDescriptors());
+ }
+ }
+ } catch (DebugException e) {
+ CDebugUIPlugin.errorDialog(ActionMessages.getString("EditRegisterGroupActionDelegate.0"), e.getStatus()); //$NON-NLS-1$
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canEditRegisterGroup(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public boolean canEditRegisterGroup(IStructuredSelection selection) {
+ IPersistableRegisterGroup group = getRegisterGroup(selection);
+ return (group != null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#removeRegisterGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void removeRegisterGroups(IStructuredSelection selection) {
+ IRegisterGroup[] groups = getRegisterGroups(selection);
+ if (groups.length > 0) {
+ IDebugTarget target = groups[0].getDebugTarget();
+ if (target instanceof ICDebugTarget) {
+ ((ICDebugTarget) target).removeRegisterGroups(groups);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canRemoveRegisterGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public boolean canRemoveRegisterGroups(IStructuredSelection selection) {
+ IRegisterGroup[] groups = getRegisterGroups(selection);
+ if (groups.length > 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#restoreDefaultGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void restoreDefaultGroups(IStructuredSelection selection) {
+ getDebugTarget(selection).restoreDefaultRegisterGroups();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canRestoreDefaultGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public boolean canRestoreDefaultGroups(IStructuredSelection selection) {
+ ICDebugTarget target = getDebugTarget(selection);
+ return (target != null) ? target.isSuspended() : false;
+ }
+
+ private ICDebugTarget getDebugTarget(IStructuredSelection selection) {
+
+ Object element = selection.getFirstElement();
+
+ if (element instanceof IDebugElement) {
+ return (ICDebugTarget) ((IDebugElement) element).getDebugTarget().getAdapter(ICDebugTarget.class);
+ }
+ return null;
+ }
+
+ private IPersistableRegisterGroup getRegisterGroup(IStructuredSelection ss) {
+ IPersistableRegisterGroup selectedGroup = null;
+ if (!ss.isEmpty()) {
+ Object s = ss.getFirstElement();
+ if (s instanceof IPersistableRegisterGroup) {
+ selectedGroup = (IPersistableRegisterGroup) s;
+ }
+ }
+
+ return selectedGroup;
+ }
+
+ private IRegisterGroup[] getRegisterGroups(IStructuredSelection ss) {
+ ArrayList<IRegisterGroup> list = new ArrayList<IRegisterGroup>();
+ for (Iterator<?> iterator = ss.iterator(); iterator.hasNext();) {
+ Object selection = iterator.next();
+ if (selection instanceof IRegisterGroup) {
+ list.add((IRegisterGroup) selection);
+ }
+ }
+
+ return list.toArray(new IRegisterGroup[list.size()]);
+ }
+
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AddRegisterGroupCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AddRegisterGroupCommandHandler.java
new file mode 100644
index 0000000000..9563d2ad9a
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/AddRegisterGroupCommandHandler.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.ui.commands;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command handler to trigger an AddRegisterGroup operation
+ */
+public class AddRegisterGroupCommandHandler extends AbstractRegisterGroupCommandHandler {
+
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ if (s instanceof IStructuredSelection) {
+ state = canAddRegisterGroup((IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection instanceof IStructuredSelection) {
+ addRegisterGroup((IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/EditRegisterGroupCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/EditRegisterGroupCommandHandler.java
new file mode 100644
index 0000000000..ba376b87e8
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/EditRegisterGroupCommandHandler.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.ui.commands;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command handler to trigger an AddRegisterGroup operation
+ */
+public class EditRegisterGroupCommandHandler extends AbstractRegisterGroupCommandHandler {
+
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ if (s instanceof IStructuredSelection) {
+ state = canEditRegisterGroup((IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection instanceof IStructuredSelection) {
+ editRegisterGroup((IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RemoveRegisterGroupsCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RemoveRegisterGroupsCommandHandler.java
new file mode 100644
index 0000000000..540c74d6ab
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RemoveRegisterGroupsCommandHandler.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.ui.commands;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command handler to trigger a RemoveRegisterGroups operation
+ */
+public class RemoveRegisterGroupsCommandHandler extends AbstractRegisterGroupCommandHandler {
+
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ if (s instanceof IStructuredSelection) {
+ state = canRemoveRegisterGroups((IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection instanceof IStructuredSelection) {
+ removeRegisterGroups((IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RestoreRegisterGroupsCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RestoreRegisterGroupsCommandHandler.java
new file mode 100644
index 0000000000..3943cca840
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/RestoreRegisterGroupsCommandHandler.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.ui.commands;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command handler to trigger an AddRegisterGroup operation
+ */
+public class RestoreRegisterGroupsCommandHandler extends AbstractRegisterGroupCommandHandler {
+
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ if (s instanceof IStructuredSelection) {
+ state = canRestoreDefaultGroups((IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection instanceof IStructuredSelection) {
+ restoreDefaultGroups((IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBPatternMatchingExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBPatternMatchingExpressions.java
index e83df89332..74fe922ae2 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBPatternMatchingExpressions.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBPatternMatchingExpressions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Ericsson and others.
+ * Copyright (c) 2012, 2014 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
@@ -9,6 +9,7 @@
* Marc Khouzam (Ericsson) - initial API and implementation
* Grzegorz Kuligowski - Cannot cast to type that contain commas (bug 393474)
* Marc Khouzam (Ericsson) - Support for glob-expressions for local variables (bug 394408)
+ * Alvaro Sanchez-Leon (Ericsson AB) - Allow user to edit register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@@ -37,9 +38,9 @@ import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IExpressions2;
import org.eclipse.cdt.dsf.debug.service.IExpressions3;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
-import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
-import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters2;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
@@ -781,41 +782,38 @@ public class GDBPatternMatchingExpressions extends AbstractDsfService implements
* @param rm RequestMonitor that will contain the unsorted matches.
*/
protected void matchRegisters(final IExpressionGroupDMContext globDmc, final DataRequestMonitor<List<IExpressionDMContext>> rm) {
- final IRegisters registerService = getServicesTracker().getService(IRegisters.class);
+ final IRegisters2 registerService = getServicesTracker().getService(IRegisters2.class);
if (registerService == null) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Register service unavailable", null)); //$NON-NLS-1$
return;
}
- registerService.getRegisterGroups(globDmc, new ImmediateDataRequestMonitor<IRegisterGroupDMContext[]>(rm) {
- @Override
- protected void handleSuccess() {
- registerService.getRegisters(
- new CompositeDMContext(new IDMContext[] { getData()[0], globDmc } ),
- new ImmediateDataRequestMonitor<IRegisterDMContext[]>(rm) {
- @Override
- protected void handleSuccess() {
- assert getData() instanceof MIRegisterDMC[];
- ArrayList<IExpressionDMContext> matches = new ArrayList<IExpressionDMContext>();
-
- String fullExpr = globDmc.getExpression().trim();
- if (fullExpr.startsWith(GLOB_EXPRESSION_PREFIX)) {
- // Strip the leading '=' and any extra spaces
- fullExpr = fullExpr.substring(1).trim();
- }
-
- for (MIRegisterDMC register : (MIRegisterDMC[])getData()) {
- String potentialMatch = REGISTER_PREFIX + register.getName();
- if (globMatches(fullExpr, potentialMatch)) {
- matches.add(createExpression(globDmc, potentialMatch));
- }
- }
-
- rm.done(matches);
+ final IContainerDMContext contDmc = DMContexts.getAncestorOfType(globDmc, IContainerDMContext.class);
+
+ registerService.getRegisters(
+ new CompositeDMContext(new IDMContext[] { contDmc, globDmc } ),
+ new ImmediateDataRequestMonitor<IRegisterDMContext[]>(rm) {
+ @Override
+ protected void handleSuccess() {
+ assert getData() instanceof MIRegisterDMC[];
+ ArrayList<IExpressionDMContext> matches = new ArrayList<IExpressionDMContext>();
+
+ String fullExpr = globDmc.getExpression().trim();
+ if (fullExpr.startsWith(GLOB_EXPRESSION_PREFIX)) {
+ // Strip the leading '=' and any extra spaces
+ fullExpr = fullExpr.substring(1).trim();
+ }
+
+ for (MIRegisterDMC register : (MIRegisterDMC[])getData()) {
+ String potentialMatch = REGISTER_PREFIX + register.getName();
+ if (globMatches(fullExpr, potentialMatch)) {
+ matches.add(createExpression(globDmc, potentialMatch));
}
- });
- }
- });
+ }
+
+ rm.done(matches);
+ }
+ });
}
/**
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java
new file mode 100644
index 0000000000..d9bda88cb3
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java
@@ -0,0 +1,1137 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson AB 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:
+ * Alvaro Sanchez-Leon (Ericsson) - First Implementation and API (Bug 235747)
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
+import org.eclipse.cdt.debug.internal.core.RegisterGroupsPersistance;
+import org.eclipse.cdt.debug.internal.core.model.IRegisterGroupDescriptor;
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.CompositeDMContext;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRegisters2;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.MIRegisters;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * <p>An extension of MIRegisters to support management of Register Groups as per the IRegisters2 interface.</p>
+ * <p>The managed registered groups are user-defined subsets of the complete list of Registers reported by GDB for a specific Target</p>
+ * <p>This class also triggers the read/write (persistence) of the user-defined Register Groups during the start/shutdown process of a session respectively</p>
+ * @since 4.6
+ */
+public class GDBRegisters extends MIRegisters implements IRegisters2 {
+
+ /**
+ * Unique temporary id for a group. 0 is reserved for the root group
+ */
+ private static int fGroupBookingCount = 1;
+
+ /**
+ * References to all groups related to a given context. Different programs may use different sets of registers e.g.
+ * 32/64 bits
+ */
+ private final ContextToGroupsMap<IContainerDMContext, MIRegisterGroupDMC[]> fContextToGroupsMap = new ContextToGroupsMap<IContainerDMContext, MIRegisterGroupDMC[]>();
+
+ /**
+ * Used to save base list of Registers associated to a group, these registers can not be used as is for
+ * "getRegisters" since the execution context may change e.g. The current selection points to a process or a running
+ * thread or a different frame, all information besides the execution context is valid.
+ */
+ private final GroupRegistersMap<MIRegisterGroupDMC, MIRegisterDMC[]> fGroupToRegistersMap = new GroupRegistersMap<MIRegisterGroupDMC, MIRegisterDMC[]>();
+
+ /**
+ * Saves the Group number to RegisterGroupDescriptor created from the serialized memento, The group number is used across contexts as the
+ * key:Integer uses a booking number incremented across container contexts
+ */
+ private final Map<Integer, IRegisterGroupDescriptor> fGroupMementoDescriptorIndex = new HashMap<Integer, IRegisterGroupDescriptor>();
+
+ public GDBRegisters(DsfSession session) {
+ super(session);
+ }
+
+ private class ContextToGroupsMap<K, V> extends HashMap<IContainerDMContext, MIRegisterGroupDMC[]> {
+ private static final long serialVersionUID = 1L;
+ private final Map<IContainerDMContext, Map<String, MIRegisterGroupDMC>> fNameToGroupMap = new HashMap<IContainerDMContext, Map<String, MIRegisterGroupDMC>>();
+
+ @Override
+ public MIRegisterGroupDMC[] put(IContainerDMContext key, MIRegisterGroupDMC[] value) {
+ if (key == null || value == null) {
+ return null;
+ }
+
+ // Contents are updated for the given context, reset this context
+ // cache
+ // So it can be rebuilt on the next get
+ fNameToGroupMap.remove(key);
+ return super.put(key, value);
+ }
+
+ @Override
+ public void clear() {
+ fNameToGroupMap.clear();
+ fGroupMementoDescriptorIndex.clear();
+ fGroupToRegistersMap.clear();
+ super.clear();
+ }
+
+ @Override
+ public MIRegisterGroupDMC[] remove(Object key) {
+ fNameToGroupMap.remove(key);
+ return super.remove(key);
+ }
+
+ public Map<String, MIRegisterGroupDMC> getGroupNameMap(IContainerDMContext key) {
+ // validate input
+ if (key == null) {
+ return null;
+ }
+
+ Map<String, MIRegisterGroupDMC> nameMap = fNameToGroupMap.get(key);
+ if (nameMap == null) {
+ // cache not resolved, rebuild
+ nameMap = new HashMap<String, MIRegisterGroupDMC>();
+ MIRegisterGroupDMC[] groupsArr = super.get(key);
+ // If the container context exist, build the name map
+ if (groupsArr != null) {
+ for (MIRegisterGroupDMC group : groupsArr) {
+ nameMap.put(group.getName(), group);
+ }
+
+ // cache it !
+ fNameToGroupMap.put(key, nameMap);
+ }
+ }
+
+ return nameMap;
+ }
+
+ /**
+ * Needed when group name(s) change but the associated group objects remain the same
+ */
+ public void resetGroupNameMap(IContainerDMContext key) {
+ fNameToGroupMap.remove(key);
+ }
+
+ /**
+ * The result will reflect the reverse order of creation, i.e. last created first
+ */
+ public MIRegisterGroupDMC[] getReversed(IDMContext key) {
+ MIRegisterGroupDMC[] groups = get(key);
+ MIRegisterGroupDMC[] reversedGroups = new MIRegisterGroupDMC[groups.length];
+ int size = groups.length;
+ for (int i = 0; i < size; i++) {
+ reversedGroups[size - 1 - i] = groups[i];
+ }
+
+ return reversedGroups;
+ }
+ }
+
+ /**
+ * Used to associate two dependent maps, Group to ordered Register[] and Group to indexed registers (Map<String,
+ * Register>)
+ */
+ private class GroupRegistersMap<K, V> extends HashMap<MIRegisterGroupDMC, MIRegisterDMC[]> {
+ private static final long serialVersionUID = 1L;
+ private final Map<MIRegisterGroupDMC, Map<String, MIRegisterDMC>> fNameToRegisterMap = new HashMap<MIRegisterGroupDMC, Map<String, MIRegisterDMC>>();
+
+ @Override
+ public MIRegisterDMC[] put(MIRegisterGroupDMC key, MIRegisterDMC[] value) {
+ // Make sure a previous entry of the key does not keep an out of
+ // date cache
+ fNameToRegisterMap.remove(key);
+ return super.put(key, value);
+ }
+
+ public Map<String, MIRegisterDMC> getIndexedRegisters(MIRegisterGroupDMC key) {
+ Map<String, MIRegisterDMC> nameToRegisterMap = fNameToRegisterMap.get(key);
+ if (nameToRegisterMap == null && get(key) != null) {
+ // Needs indexing
+ nameToRegisterMap = indexRegisters(key);
+ if (nameToRegisterMap != null) {
+ fNameToRegisterMap.put(key, nameToRegisterMap);
+ }
+ }
+
+ return nameToRegisterMap;
+ }
+
+ @Override
+ public void clear() {
+ fNameToRegisterMap.clear();
+ super.clear();
+ }
+
+ @Override
+ public MIRegisterDMC[] remove(Object key) {
+ fNameToRegisterMap.remove(key);
+ return super.remove(key);
+ }
+
+ private Map<String, MIRegisterDMC> indexRegisters(MIRegisterGroupDMC registerGroup) {
+ MIRegisterDMC[] registers = super.get(registerGroup);
+ if (registers == null || registers.length < 1) {
+ return null;
+ }
+
+ Map<String, MIRegisterDMC> registerNameMap = new HashMap<String, MIRegisterDMC>();
+ for (IRegisterDMContext register : registers) {
+ assert(register instanceof MIRegisterDMC);
+ MIRegisterDMC registerDmc = (MIRegisterDMC) register;
+ registerNameMap.put(registerDmc.getName(), registerDmc);
+ }
+
+ return registerNameMap;
+ }
+ }
+
+ private class RegisterGroupDescriptor implements IRegisterGroupDescriptor {
+ private final boolean fEnabled;
+ private final MIRegisterGroupDMC fgroup;
+
+ public RegisterGroupDescriptor(MIRegisterGroupDMC group, boolean enabled) {
+ fgroup = group;
+ fEnabled = enabled;
+ }
+
+ @Override
+ public String getName() {
+ return fgroup.getName();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return fEnabled;
+ }
+
+ @Override
+ public IRegisterDescriptor[] getChildren() throws CoreException {
+ IRegisterDescriptor[] regDescriptors = null;
+ // Get a snap shot of the current registers
+ MIRegisterDMC[] registers = fGroupToRegistersMap.get(fgroup);
+ if (registers != null && registers.length > 0) {
+ regDescriptors = new IRegisterDescriptor[registers.length];
+ for (int i = 0; i < registers.length; i++) {
+ regDescriptors[i] = new RegisterDescriptor(registers[i]);
+ }
+ } else {
+ // The registers were probably never fetched, obtain the
+ // original definitions from deserialized groups
+ IRegisterGroupDescriptor groupMementoDescriptor = fGroupMementoDescriptorIndex.get(fgroup.getGroupNo());
+ if (groupMementoDescriptor != null) {
+ regDescriptors = groupMementoDescriptor.getChildren();
+ }
+ }
+
+ return regDescriptors;
+ }
+
+ }
+
+ private class RegisterDescriptor implements IRegisterDescriptor {
+ private final MIRegisterDMC fRegister;
+ private final static String ORIGINAL_GROUP_NAME = "Main"; //$NON-NLS-1$
+
+ public RegisterDescriptor(MIRegisterDMC register) {
+ fRegister = register;
+ }
+
+ @Override
+ public String getName() {
+ return fRegister.getName();
+ }
+
+ @Override
+ public String getGroupName() {
+ // Hard coded to keep compatibility with CDI's format
+ return ORIGINAL_GROUP_NAME;
+ }
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new ImmediateRequestMonitor(requestMonitor) {
+ @Override
+ public void handleSuccess() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+ register(new String[]{IRegisters.class.getName(),
+ IRegisters2.class.getName(),
+ MIRegisters.class.getName(),
+ GDBRegisters.class.getName()}, new Hashtable<String,String>());
+ requestMonitor.done();
+ }
+
+ @Override
+ public void getRegisterGroups(final IDMContext ctx, final DataRequestMonitor<IRegisterGroupDMContext[]> rm) {
+ final IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
+ if (contDmc == null) {
+ IStatus status = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Container context not provided, unable to get Register Groups", null); //$NON-NLS-1$
+ rm.setStatus(status);
+ rm.done();
+ return;
+ }
+
+ if (fContextToGroupsMap.containsKey(contDmc)) {
+ // The groups information is already available and can be returned
+ rm.setData(fContextToGroupsMap.getReversed(contDmc));
+ rm.done();
+ return;
+ }
+
+ // The register groups information needs to be built from GDB and user-defined groups i.e. de-serialized
+ // from the launch configuration.
+ super.getRegisterGroups(ctx, new ImmediateDataRequestMonitor<IRegisterGroupDMContext[]>(rm) {
+ @Override
+ @ConfinedToDsfExecutor("fExecutor")
+ protected void handleSuccess() {
+ final IRegisterGroupDMContext[] regGroups = getData();
+ // only one group from MI is expected at the moment
+ assert (regGroups.length == 1);
+ assert (regGroups[0] instanceof MIRegisterGroupDMC);
+
+ final MIRegisterGroupDMC miGroup = (MIRegisterGroupDMC) regGroups[0];
+
+ // read serialized groups
+ MIRegisterGroupDMC[] mementoGroups = readGroupsFromMemento(contDmc);
+
+ // Track the groups associated to this context
+ // The root group (mi) is placed and expected at index 0 followed
+ // by the user groups read from the memento
+ MIRegisterGroupDMC[] regGroupsCtx = concatenateArr(new MIRegisterGroupDMC[] { miGroup }, mementoGroups);
+
+ // Have the information ready for subsequent request or group operations.
+ fContextToGroupsMap.put(contDmc, regGroupsCtx);
+
+ // Reverse the order i.e. latest on top and get back to parent monitor
+ rm.setData(fContextToGroupsMap.getReversed(contDmc));
+ rm.done();
+ }
+ });
+ }
+
+ @Override
+ public void getRegisterGroupData(final IRegisterGroupDMContext regGroupDmc,
+ final DataRequestMonitor<IRegisterGroupDMData> rm) {
+
+ assert (regGroupDmc instanceof MIRegisterGroupDMC);
+
+ if (regGroupDmc instanceof MIRegisterGroupDMC) {
+ MIRegisterGroupDMC groupDmc = (MIRegisterGroupDMC) regGroupDmc;
+ rm.setData(createRegisterGroupData(groupDmc));
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
+ "Unable to resolve Group Data, Invalid Register Group provided", null)); //$NON-NLS-1$
+ }
+
+ rm.done();
+ }
+
+ private IRegisterGroupDMData createRegisterGroupData(final MIRegisterGroupDMC groupDmc) {
+
+ IRegisterGroupDMData groupData = new IRegisterGroupDMData() {
+ @Override
+ public String getName() {
+ return groupDmc.getName();
+ }
+
+ @Override
+ public String getDescription() {
+ if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
+ return ROOT_GROUP_DESCRIPTION;
+ }
+
+ return BLANK_STRING;
+ }
+
+ };
+
+ // Make sure this group is available in the groups to registers map,
+ // as this map provides the input to save /serialize the groups
+ // The associated registers will be resolved upon request.
+ if (fGroupToRegistersMap.get(groupDmc) == null) {
+ fGroupToRegistersMap.put(groupDmc, new MIRegisterDMC[0]);
+ }
+
+ return groupData;
+ }
+
+ @Override
+ public void getRegisters(final IDMContext aCtx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
+ findRegisterGroup(aCtx, ROOT_GROUP_NAME, new ImmediateDataRequestMonitor<IRegisterGroupDMContext>() {
+ @Override
+ protected void handleSuccess() {
+ //Get the root group, needed as a possible default group and to resolve target registers
+ IRegisterGroupDMContext rootGroup = getData();
+ assert (rootGroup instanceof MIRegisterGroupDMC);
+ final MIRegisterGroupDMC rootGroupContext = (MIRegisterGroupDMC) rootGroup;
+
+ //if the received context does not contain a register group i.e.is null, the default group to resolve registers is the root group
+ MIRegisterGroupDMC tGroupDmc = DMContexts.getAncestorOfType(aCtx, MIRegisterGroupDMC.class);
+
+ IDMContext tCtx = aCtx;
+ if (tGroupDmc == null) {
+ tGroupDmc = rootGroupContext;
+ //We need a register group as part of the context to resolve registers
+ tCtx = new CompositeDMContext(new IDMContext[] {aCtx, tGroupDmc});
+ }
+
+ final IDMContext ctx = tCtx;
+
+ final MIRegisterGroupDMC groupDmc = tGroupDmc;
+ // check if base registers have been loaded already
+ MIRegisterDMC[] baseRegisters = fGroupToRegistersMap.get(groupDmc);
+ if (baseRegisters != null && baseRegisters.length > 0) {
+ // use baseRegisters to build registers associated to the given context
+ buildGroupRegisters(ctx, baseRegisters, rm);
+ return;
+ }
+
+ IContainerDMContext rootGroupContainer = DMContexts.getAncestorOfType(rootGroupContext,
+ IContainerDMContext.class);
+ MIRegisterDMC[] registerBase = fGroupToRegistersMap.get(rootGroupContainer);
+ if (registerBase == null || registerBase.length < 1) {
+ // Prepare to fetch the register information from GDB (root group)
+ // Include the frame/execution context whenever available
+ IDMContext miExecDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
+ if (miExecDmc == null) {
+ miExecDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
+ }
+
+ // if Execution context is not available return shallow registers i.e. no execution context
+ final CompositeDMContext compCtx;
+ if (miExecDmc != null) {
+ compCtx = new CompositeDMContext(new IDMContext[] { rootGroupContext, miExecDmc });
+ } else {
+ compCtx = new CompositeDMContext(new IDMContext[] { rootGroupContext });
+ }
+
+ // Fetch the register base from GDB
+ GDBRegisters.super.getRegisters(compCtx, new DataRequestMonitor<IRegisterDMContext[]>(getExecutor(), rm) {
+ @Override
+ @ConfinedToDsfExecutor("fExecutor")
+ protected void handleSuccess() {
+ IRegisterDMContext[] iregisters = getData();
+ MIRegisterDMC[] registers = Arrays.copyOf(iregisters, iregisters.length, MIRegisterDMC[].class);
+
+ // associate group to bare registers i.e. not associated to a specific execution context
+ fGroupToRegistersMap.put(rootGroupContext, toBareRegisters(registers));
+ if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
+ buildGroupRegisters(ctx, registers, rm);
+ return;
+ }
+
+ // Now proceed to resolve the requested user group registers
+ getUserGroupRegisters(ctx, rm);
+ }
+ });
+ } else {
+ if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
+ buildGroupRegisters(ctx, registerBase, rm);
+ } else {
+ // resolve user group registers
+ getUserGroupRegisters(ctx, rm);
+ }
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public void canAddRegisterGroup(IDMContext selectionContext, DataRequestMonitor<Boolean> rm) {
+ // Not relevant checks at this point
+ rm.setData(true);
+ rm.done();
+ }
+
+ @Override
+ public void addRegisterGroup(final IDMContext containerContext, final String groupName, final IRegisterDMContext[] registers, RequestMonitor rm) {
+ if (registers == null || registers.length < 1) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ Messages.RegisterGroup_invalid_number_of_registers, null));
+ rm.done();
+ return;
+ }
+
+ if (groupName.trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ NLS.bind(Messages.RegisterGroup_name_reserved, ROOT_GROUP_NAME), null));
+ rm.done();
+ return;
+ }
+
+ if (!(registers[0] instanceof MIRegisterDMC)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Unexpected IRegisterDMContext input instance type", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ IContainerDMContext contDmc = DMContexts.getAncestorOfType(registers[0], IContainerDMContext.class);
+ if (contDmc == null) {
+ contDmc = DMContexts.getAncestorOfType(containerContext, IContainerDMContext.class);
+ if (contDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Unable to add Register group, Invalid Container", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ }
+
+ // must be a child of an existing container, at least the root group must be present
+ assert (fContextToGroupsMap.containsKey(contDmc));
+
+ // Make sure the name is not currently in use
+ if (fContextToGroupsMap.getGroupNameMap(contDmc).get(groupName) != null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, NLS.bind(
+ Messages.RegisterGroup_name_used, groupName), null));
+ rm.done();
+ return;
+ }
+
+ //create the new group
+ MIRegisterGroupDMC group = new MIRegisterGroupDMC(this, contDmc, fGroupBookingCount, groupName);
+ fGroupBookingCount++;
+
+ // Update the context to groups map including the new group
+ fContextToGroupsMap.put(contDmc,
+ concatenateArr(fContextToGroupsMap.get(contDmc), new MIRegisterGroupDMC[] { group }));
+
+ //type adjustment
+ MIRegisterDMC[] miRegisters = Arrays.copyOf(registers, registers.length, MIRegisterDMC[].class);
+
+ // associate group to bare registers i.e. not associated to a specific execution context
+ MIRegisterDMC[] bareRegisters = toBareRegisters(miRegisters);
+ fGroupToRegistersMap.put(group, bareRegisters);
+
+ // Create event notification, to trigger the UI refresh
+ getSession().dispatchEvent(new GroupsChangedDMEvent(contDmc), null);
+ rm.done();
+ }
+
+ @Override
+ public void canEditRegisterGroup(IRegisterGroupDMContext group, DataRequestMonitor<Boolean> rm) {
+ rm.setData(canEditRegisterGroup(group));
+ rm.done();
+ }
+
+ @Override
+ public void editRegisterGroup(IRegisterGroupDMContext group, String newGroupName, IRegisterDMContext[] iRegisters,
+ RequestMonitor rm) {
+
+ if (iRegisters != null && iRegisters.length == 0) {
+ rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ Messages.RegisterGroup_invalid_number_of_registers, null));
+ return;
+ }
+
+ if (!(group instanceof MIRegisterGroupDMC)) {
+ rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown DMC type", null)); //$NON-NLS-1$
+ return;
+ }
+
+ IContainerDMContext contDmc = DMContexts.getAncestorOfType(group, IContainerDMContext.class);
+ if (contDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Unable to edit Register group, Invalid Container", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ MIRegisterGroupDMC miGroup = ((MIRegisterGroupDMC) group);
+
+ if (!canEditRegisterGroup(group)) {
+ // Should not happen as canEdit is expected to be called before edit
+ rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot currently edit register groups", null)); //$NON-NLS-1$
+ return;
+ }
+
+ if (newGroupName != null && !newGroupName.isEmpty()) {
+ // Make sure the new group name is not the reserved root group name
+ if (newGroupName.trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ NLS.bind(Messages.RegisterGroup_name_reserved, ROOT_GROUP_NAME), null));
+ rm.done();
+ return;
+ }
+
+ // Make sure the name is not currently in use
+ if (!miGroup.getName().equals(newGroupName)) {
+ // we are updating the name, lets make sure this new name is not in use
+ if (fContextToGroupsMap.getGroupNameMap(contDmc).get(newGroupName) != null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ NLS.bind(Messages.RegisterGroup_name_used, newGroupName), null));
+ rm.done();
+ return;
+ }
+ }
+
+ miGroup.setName(newGroupName);
+
+ //make sure we update the group name cache
+ fContextToGroupsMap.resetGroupNameMap(contDmc);
+
+ generateRegisterGroupChangedEvent(miGroup);
+ } else {
+ // Request to keep name the same
+ }
+
+ if (iRegisters != null) {
+ assert (iRegisters.length > 0);
+
+ // transform to MIRegistersDMC[]
+ MIRegisterDMC[] registers = arrangeRegisters(iRegisters);
+
+ // preserve registers in a general format not associated to a specific frame
+ registers = toBareRegisters(registers);
+ fGroupToRegistersMap.put(miGroup, registers);
+ // Notify of Registers changed
+ generateRegistersChangedEvent(miGroup);
+ } else {
+ // Request to keep register list the same
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.cdt.dsf.debug.service.IRegisters2#removeRegisterGroups(org.eclipse.cdt.dsf.debug.service.IRegisters
+ * .IRegisterGroupDMContext[], org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ @Override
+ public void removeRegisterGroups(IRegisterGroupDMContext[] groups, RequestMonitor rm) {
+ removeRegisterGroups(groups, false, rm);
+ }
+
+ @Override
+ public void restoreDefaultGroups(final IDMContext selectionContext, final RequestMonitor rm) {
+ for (IDMContext context : fContextToGroupsMap.keySet()) {
+ removeRegisterGroups(context);
+ }
+
+ // clean the serialized registers group information
+ save();
+
+ // Clear all global references to the contexts and groups
+ fContextToGroupsMap.clear();
+ rm.done();
+ }
+
+ /**
+ * Reset this class i.e. does not impact saved groups within launch configuration
+ *
+ * @param rm
+ */
+ public void reset(final RequestMonitor rm) {
+ for (IDMContext context : fContextToGroupsMap.keySet()) {
+ removeRegisterGroups(context);
+ }
+
+ // Clear all global references to the contexts and groups
+ fContextToGroupsMap.clear();
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.dsf.mi.service.MIRegisters#findRegisterGroup(org.eclipse.cdt.dsf.datamodel.IDMContext,
+ * java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ @Override
+ public void findRegisterGroup(final IDMContext ctx, final String name, final DataRequestMonitor<IRegisterGroupDMContext> rm) {
+ final IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
+ if (contDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Container context not found", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ if (fContextToGroupsMap.get(ctx) == null) {
+ // Need to build the list of register groups including the one from target
+ getRegisterGroups(contDmc, new DataRequestMonitor<IRegisterGroupDMContext[]>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // Using the list of groups indirectly to find the one with the given name from it
+ findRegisterGroup(contDmc, name, rm);
+ }
+ });
+ } else {
+ // The context to groups map has been initialized and can be used
+ findRegisterGroup(contDmc, name, rm);
+ }
+ }
+
+ /**
+ * Call it only after getRegisterGroups has been called at least once, so the context to groups map is not empty
+ */
+ private void findRegisterGroup(IContainerDMContext contDmc, String name, DataRequestMonitor<IRegisterGroupDMContext> rm) {
+ Map<String, MIRegisterGroupDMC> nameToGroup = fContextToGroupsMap.getGroupNameMap(contDmc);
+ if (nameToGroup != null) {
+ rm.setData(nameToGroup.get(name));
+ } else {
+ rm.setData(null);
+ }
+
+ rm.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor rm) {
+ save();
+ super.shutdown(rm);
+ }
+
+ public void save() {
+ IRegisterGroupDescriptor[] groups = buildDescriptors();
+ ILaunchConfiguration launchConfig = getLaunchConfig();
+ if (launchConfig != null) {
+ RegisterGroupsPersistance serializer = new RegisterGroupsPersistance(launchConfig);
+ try {
+ serializer.saveGroups(groups);
+ } catch (CoreException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Cast to MI and sort them ascending order by register index
+ */
+ private MIRegisterDMC[] arrangeRegisters(IRegisterDMContext[] iRegisters) {
+ TreeMap<Integer, MIRegisterDMC> sortedRegisters = new TreeMap<Integer, MIRegisterDMC>();
+ for (int i = 0; i < iRegisters.length; i++) {
+ assert(iRegisters[i] instanceof MIRegisterDMC);
+ MIRegisterDMC register = (MIRegisterDMC) iRegisters[i];
+ sortedRegisters.put(register.getRegNo(), register);
+ }
+
+ return sortedRegisters.values().toArray(new MIRegisterDMC[sortedRegisters.size()]);
+ }
+
+ /**
+ * @param groups
+ * - The groups to be removed
+ * @param removeRoot
+ * - indicates if the root group needs to be removed e.g. during restore to defaults
+ * @param rm
+ */
+ private void removeRegisterGroups(IRegisterGroupDMContext[] groups, boolean removeRoot, RequestMonitor rm) {
+ if (groups != null) {
+ // Save a list of updated containers to only send an update event for each of them
+ final Set<IContainerDMContext> updatedContainers = new HashSet<IContainerDMContext>();
+ for (IRegisterGroupDMContext group : groups) {
+
+ if (!removeRoot) {
+ // Prevent removal of the Root Group
+ if (!(group instanceof MIRegisterGroupDMC)) {
+ // All groups are expected to be instances of MIREgisterGroupDMC
+ assert (false);
+ continue;
+ }
+
+ if (((MIRegisterGroupDMC) group).getName().equals(ROOT_GROUP_NAME)) {
+ // Skip removal of a root group, except when restoring to default groups
+ continue;
+ }
+ }
+
+ final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(group, IContainerDMContext.class);
+
+ // All given groups are expected to be part of the same Container, however it's safer to create a new list
+ // per context to cover the unsual case
+ // This could be revisited in case there is performance concerns which does not seem an issue at this
+ // point.
+ MIRegisterGroupDMC[] groupsCtx = fContextToGroupsMap.get(containerDmc);
+ assert(groupsCtx != null);
+
+ if (groupsCtx != null) {
+ List<MIRegisterGroupDMC> groupsList = new ArrayList<MIRegisterGroupDMC>(Arrays.asList(groupsCtx));
+
+ // Removing a single group
+ groupsList.remove(group);
+
+ // Back to context map without the given group
+ fContextToGroupsMap.put(containerDmc, groupsList.toArray(new MIRegisterGroupDMC[groupsList.size()]));
+ // Now remove the group from the groups to registers map
+ if (fGroupToRegistersMap.remove(group) != null) {
+ updatedContainers.add(containerDmc);
+ }
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Unable to remove Register group, Invalid Container", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ }
+
+ // Sending only one update per container
+ for (IContainerDMContext container : updatedContainers) {
+ getSession().dispatchEvent(new GroupsChangedDMEvent(container), null);
+ }
+ }
+
+ rm.done();
+ }
+
+ private void removeRegisterGroups(IDMContext containerDmc) {
+ MIRegisterGroupDMC[] groups = fContextToGroupsMap.get(containerDmc);
+ if (groups != null) {
+ removeRegisterGroups(groups, true, new RequestMonitor(getExecutor(), null) {
+ });
+ }
+ }
+
+ private boolean canEditRegisterGroup(IRegisterGroupDMContext group) {
+ if (group instanceof MIRegisterGroupDMC) {
+ MIRegisterGroupDMC miGroup = ((MIRegisterGroupDMC) group);
+ // Prevent changes to the root group
+ if (miGroup.getName().trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
+ return false;
+ }
+
+ // Expected to be on the existing groups map
+ if (fGroupToRegistersMap.containsKey(group)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private ILaunchConfiguration getLaunchConfig() {
+ ILaunch launch = (ILaunch) getSession().getModelAdapter(ILaunch.class);
+ if (launch == null) {
+ // The launch is no longer active
+ return null;
+ }
+
+ ILaunchConfiguration config = launch.getLaunchConfiguration();
+ return config;
+ }
+
+ private IRegisterGroupDescriptor[] buildDescriptors() {
+ // use a tree map to sort the entries by group number
+ TreeMap<Integer, MIRegisterGroupDMC> sortedGroups = new TreeMap<Integer, MIRegisterGroupDMC>();
+
+ for (MIRegisterGroupDMC group : fGroupToRegistersMap.keySet()) {
+ sortedGroups.put(Integer.valueOf(group.getGroupNo()), group);
+ }
+
+ // Not serializing the root group which is dynamically created from GDB
+ sortedGroups.remove(Integer.valueOf(0));
+
+ Set<Entry<Integer, MIRegisterGroupDMC>> groupSet = sortedGroups.entrySet();
+ IRegisterGroupDescriptor[] descriptors = new IRegisterGroupDescriptor[groupSet.size()];
+
+ // load group descriptors sorted in ascending order to their group
+ // number into the result array
+ int i = 0;
+ for (Iterator<Entry<Integer, MIRegisterGroupDMC>> iterator = groupSet.iterator(); iterator.hasNext();) {
+ Entry<Integer, MIRegisterGroupDMC> entry = iterator.next();
+ descriptors[i] = new RegisterGroupDescriptor(entry.getValue(), true);
+ i++;
+ }
+
+ return descriptors;
+ }
+
+ private <T> T[] concatenateArr(T[] origArr, T[] deltaArr) {
+ if (origArr == null) {
+ return deltaArr;
+ }
+
+ if (deltaArr == null) {
+ return origArr;
+ }
+
+ T[] newArr = Arrays.copyOf(origArr, origArr.length + deltaArr.length);
+ System.arraycopy(deltaArr, 0, newArr, origArr.length, deltaArr.length);
+ return newArr;
+ }
+
+ private MIRegisterGroupDMC[] readGroupsFromMemento(final IContainerDMContext contDmc) {
+ RegisterGroupsPersistance deserializer = new RegisterGroupsPersistance(getLaunchConfig());
+ IRegisterGroupDescriptor[] groupDescriptions = deserializer.parseGroups();
+
+ List<MIRegisterGroupDMC> groups = new ArrayList<MIRegisterGroupDMC>();
+ for (IRegisterGroupDescriptor group : groupDescriptions) {
+ fGroupMementoDescriptorIndex.put(fGroupBookingCount, group);
+ groups.add(new MIRegisterGroupDMC(this, contDmc, fGroupBookingCount, group.getName()));
+ fGroupBookingCount++;
+ }
+
+ return groups.toArray(new MIRegisterGroupDMC[groups.size()]);
+ }
+
+ private void getUserGroupRegisters(IDMContext ctx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
+ final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);
+
+ // Need to build the corresponding register[] from the memento descriptors
+ IRegisterGroupDescriptor grpDescriptor = fGroupMementoDescriptorIndex.get(groupDmc.getGroupNo());
+
+ if (grpDescriptor == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
+ "The Register Group Descriptor does not exist for group: " + groupDmc.getName(), null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ MIRegisterDMC[] registers;
+ try {
+ // Resolve bare registers from the memento descriptors
+ registers = resolveRegisters(grpDescriptor, ctx);
+ } catch (CoreException e) {
+ rm.setStatus(e.getStatus());
+ rm.done();
+ return;
+ }
+
+ // update internal data
+ fGroupToRegistersMap.put(groupDmc, registers);
+
+ // now resolve to context specific registers
+ buildGroupRegisters(ctx, registers, rm);
+ }
+
+ /**
+ * Resolve register dmcs from de-serialized memento descriptors
+ */
+ private MIRegisterDMC[] resolveRegisters(IRegisterGroupDescriptor grpDescriptor, IDMContext ctx)
+ throws CoreException {
+ final List<MIRegisterDMC> registerContexts = new ArrayList<MIRegisterDMC>();
+ final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
+ final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);
+
+ IRegisterDescriptor[] registerDescriptions = grpDescriptor.getChildren();
+ MIRegisterGroupDMC[] groupContexts = fContextToGroupsMap.get(containerDmc);
+ if (groupContexts != null && groupContexts.length > 0) {
+ // Get the General Group (base) at index 0,
+ // Registers map indexed by name
+ Map<String, MIRegisterDMC> indexedRegisterBase = fGroupToRegistersMap.getIndexedRegisters(groupContexts[0]);
+
+ // For each descriptors find its corresponding MIRegisterDMC
+ for (IRegisterDescriptor registerDescription : registerDescriptions) {
+ MIRegisterDMC registerDmc = indexedRegisterBase.get(registerDescription.getName());
+ if (registerDmc == null) {
+ // The Register is not present from the base received from GDB
+ // Create a register DMC with no execution dmc and invalid
+ // register number e.g. not mapped to a gdb register.
+ registerDmc = new MIRegisterDMC(this, groupDmc, -1, registerDescription.getName());
+ }
+
+ registerContexts.add(registerDmc);
+ }
+ }
+
+ return registerContexts.toArray(new MIRegisterDMC[registerContexts.size()]);
+ }
+
+ @Override
+ protected void generateRegisterChangedEvent(final IRegisterDMContext dmc) {
+ // notify the register value change
+ getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());
+
+
+ // Propagate notification to all groups.
+ // A change of a single register needs to be propagated to all groups within the same Container/Process
+ // I.e. Some registers are dependent on the value of others and these dependent registers could be
+ // associated to different groups.
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
+ generateRegistersChangedEvent(containerDmc);
+ }
+
+ private void generateRegistersChangedEvent(IContainerDMContext containerDmc) {
+ //resolve the groups for the current container (process) context
+ final MIRegisterGroupDMC[] groups = fContextToGroupsMap.get(containerDmc);
+
+ //trigger notification to all groups in the container
+ for (int i = 0; i < groups.length; i++) {
+ //We need final locals variables from the loop. Use a method call for this
+ generateRegistersChangedEvent(groups[i]);
+ }
+ }
+
+ private void generateRegistersChangedEvent(final MIRegisterGroupDMC groupDmc) {
+ IRegistersChangedDMEvent event = new IRegistersChangedDMEvent() {
+ @Override
+ public IRegisterGroupDMContext getDMContext() {
+ return groupDmc;
+ }
+ };
+
+ getSession().dispatchEvent(event, getProperties());
+ }
+
+ private void generateRegisterGroupChangedEvent(final MIRegisterGroupDMC groupDmc) {
+ IGroupChangedDMEvent event = new IGroupChangedDMEvent() {
+ @Override
+ public IRegisterGroupDMContext getDMContext() {
+ return groupDmc;
+ }
+ };
+
+ getSession().dispatchEvent(event, getProperties());
+ }
+
+
+
+ /**
+ * Create Registers from specific execution context to a generic register context, e.g. not associated to a specific
+ * execution context.
+ */
+ private MIRegisterDMC[] toBareRegisters(MIRegisterDMC[] registers) {
+
+ MIRegisterDMC[] bareRegisters = new MIRegisterDMC[registers.length];
+ for (int i = 0; i < registers.length; i++) {
+ // only one parent i.e. group context
+ MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(registers[i], MIRegisterGroupDMC.class);
+ assert (groupDmc != null);
+ bareRegisters[i] = new MIRegisterDMC(this, groupDmc, registers[i].getRegNo(), registers[i].getName());
+ }
+
+ return bareRegisters;
+ }
+
+ private void buildGroupRegisters(final IDMContext ctx, final MIRegisterDMC[] baseRegisters,
+ final DataRequestMonitor<IRegisterDMContext[]> rm) {
+ final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);
+
+ assert (groupDmc != null);
+
+ final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
+ if (frameDmc == null) {
+ // The selection does not provide a specific frame, then resolve the top frame on the current thread
+ // if the execution frame is not available proceed with no frame context i.e. will not be able to resolve
+ // values.
+ IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
+ if (execDmc != null) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService != null) {
+ stackService.getTopFrame(execDmc, new ImmediateDataRequestMonitor<IStack.IFrameDMContext>(rm) {
+ @Override
+ protected void handleSuccess() {
+ cloneRegistersToContext(groupDmc, getData(), baseRegisters, rm);
+ }
+
+ @Override
+ protected void handleFailure() {
+ // Unable to resolve top frame on current thread.
+ // The thread could e.g. be in running state,
+ // we return register instances with no associated execution context
+ // i.e. unable to resolve its associated value.
+ cloneRegistersToContext(groupDmc, null, baseRegisters, rm);
+ }
+ });
+
+ return;
+ }
+ }
+ }
+
+ cloneRegistersToContext(groupDmc, frameDmc, baseRegisters, rm);
+ }
+
+ /**
+ * Create a new array of register instances with the given context
+ */
+ private void cloneRegistersToContext(MIRegisterGroupDMC groupDmc, IFrameDMContext frameDmc,
+ MIRegisterDMC[] baseRegisters, DataRequestMonitor<IRegisterDMContext[]> rm) {
+ MIRegisterDMC[] registers = new MIRegisterDMC[baseRegisters.length];
+ if (frameDmc != null) {
+ // build to valid stack frame context
+ for (int i = 0; i < registers.length; i++) {
+ registers[i] = new MIRegisterDMC(this, groupDmc, frameDmc, baseRegisters[i].getRegNo(),
+ baseRegisters[i].getName());
+ }
+ } else {
+ // build with no execution context, normal case if a selection is pointing to
+ // e.g. a running thread, a process.. i.e. not able to associate register values.
+ for (int i = 0; i < registers.length; i++) {
+ registers[i] = new MIRegisterDMC(this, groupDmc, baseRegisters[i].getRegNo(),
+ baseRegisters[i].getName());
+ }
+ }
+
+ // return the registers
+ rm.setData(registers);
+ rm.done();
+ }
+
+ @Override
+ public void canRemoveRegisterGroups(IRegisterGroupDMContext[] groups, DataRequestMonitor<Boolean> rm) {
+ if (groups == null || groups.length < 1) {
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+
+ for(IRegisterGroupDMContext group : groups) {
+ assert(group instanceof MIRegisterGroupDMC);
+ MIRegisterGroupDMC miGroup = (MIRegisterGroupDMC) group;
+ if (miGroup.getName().equals(ROOT_GROUP_NAME)) {
+ // Not allowed to remove the root group
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+ }
+
+ rm.setData(true);
+ rm.done();
+
+ }
+
+ @Override
+ public void canRestoreDefaultGroups(IDMContext selectionContext, DataRequestMonitor<Boolean> rm) {
+ // Not relevant checks at this point
+ rm.setData(true);
+ rm.done();
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
index 6e62fd373b..924f4cf973 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
@@ -17,6 +17,7 @@
* William Riley (Renesas) - Support for GDB 7.3 disassembly service (Bug 357270)
* Marc Khouzam (Ericsson) - Support for GDB 7.4 processes service (Bug 389945)
* Marc Khouzam (Ericsson) - Support dynamic printf in bp service 7.5 (Bug 400628)
+ * Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@@ -48,7 +49,6 @@ import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
import org.eclipse.cdt.dsf.mi.service.MIModules;
-import org.eclipse.cdt.dsf.mi.service.MIRegisters;
import org.eclipse.cdt.dsf.mi.service.MIStack;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.service.DsfSession;
@@ -231,7 +231,7 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
@Override
protected IRegisters createRegistersService(DsfSession session) {
- return new MIRegisters(session);
+ return new GDBRegisters(session);
}
@Override
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
index 13f6e68101..cc3da86b09 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2013 Ericsson and others.
+ * Copyright (c) 2012, 2014 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:
* Marc Khouzam (Ericsson) - initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Bug 235747
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@@ -25,6 +26,9 @@ class Messages extends NLS {
public static String UniqueMatch;
public static String UniqueMatches;
public static String ErrorNotSupported;
+ public static String RegisterGroup_name_reserved;
+ public static String RegisterGroup_name_used;
+ public static String RegisterGroup_invalid_number_of_registers;
static {
// initialize resource bundle
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
index 8a6245c7a1..96bdbce717 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2012 Ericsson and others.
+# Copyright (c) 2012, 2014 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:
# Marc Khouzam (Ericsson) - initial API and implementation
+# Alvaro Sanchez-Leon (Ericsson) - Support Register Groups (Bug 235747)
###############################################################################
Tracing_not_supported_error=Tracing not supported
@@ -17,3 +18,6 @@ NoMatches=No matches
UniqueMatch={0} unique match
UniqueMatches={0} unique matches
ErrorNotSupported=Operation not supported with this GDB version
+RegisterGroup_name_reserved=The group name "{0}" is reserved
+RegisterGroup_name_used=The group name "{0}" is already in use
+RegisterGroup_invalid_number_of_registers=A minimum of one register is needed for a Register Group
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
index e0239b8942..cf7de936f0 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems and others.
+ * Copyright (c) 2006, 2014 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
@@ -11,6 +11,7 @@
* Roland Grunberg (RedHat) - Refresh all registers once one is changed (Bug 400840)
* Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
* Alvaro Sanchez-Leon (Ericsson) - Register view does not refresh register names per process (Bug 418176)
+ * Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@@ -66,7 +67,18 @@ import org.osgi.framework.BundleContext;
*/
public class MIRegisters extends AbstractDsfService implements IRegisters, ICachingService {
- private static final String BLANK_STRING = ""; //$NON-NLS-1$
+ /**
+ * @since 4.6
+ */
+ protected static final String BLANK_STRING = ""; //$NON-NLS-1$
+ /**
+ * @since 4.6
+ */
+ protected static final String ROOT_GROUP_NAME = Messages.MIRegisters_General_Registers;
+ /**
+ * @since 4.6
+ */
+ protected static final String ROOT_GROUP_DESCRIPTION = Messages.MIRegisters_General_Registers_description;
/*
* Support class used to construct Register Group DMCs.
*/
@@ -83,6 +95,12 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
public int getGroupNo() { return fGroupNo; }
public String getName() { return fGroupName; }
+ /**
+ * @since 4.6
+ */
+ public void setName(String groupName) {
+ fGroupName = groupName;
+ }
@Override
public boolean equals(Object other) {
@@ -93,7 +111,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
@Override
public int hashCode() { return super.baseHashCode() ^ fGroupNo; }
@Override
- public String toString() { return baseToString() + ".group[" + fGroupNo + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+ public String toString() { return baseToString() + ".group[" + fGroupNo + "," + fGroupName + "]"; } //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
/*
@@ -125,20 +143,20 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
/**
- * This Register context is associated to two parent contexts. A stack frame context (IFrameDMContext), and a register group
- * context (MIRegisterGroupDMC). When the scenario requires to build a register contexts from the selection of a thread, then the top
- * frame shall be resolved and be provided in this constructor.
+ * This Register context is associated to two parent contexts. A stack frame context (IFrameDMContext), and a
+ * register group context (MIRegisterGroupDMC). When the scenario requires to build a register contexts from the
+ * selection of a thread, then the top frame shall be resolved and be provided in this constructor.
*
* The frame context is necessary to resolve the register's data e.g. value
*
* @since 4.3
*/
- public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IFrameDMContext frameDmc, int regNo, String regName) {
- super(service.getSession().getId(),
- new IDMContext[] { frameDmc, group });
- fRegNo = regNo;
- fRegName = regName;
- }
+ public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IFrameDMContext frameDmc, int regNo,
+ String regName) {
+ super(service.getSession().getId(), new IDMContext[] { frameDmc, group });
+ fRegNo = regNo;
+ fRegName = regName;
+ }
public int getRegNo() { return fRegNo; }
public String getName() { return fRegName; }
@@ -162,7 +180,10 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
private final IRegisterDMContext fRegisterDmc;
- RegisterChangedDMEvent(IRegisterDMContext registerDMC) {
+ /**
+ * @since 4.6
+ */
+ public RegisterChangedDMEvent(IRegisterDMContext registerDMC) {
fRegisterDmc = registerDMC;
}
@@ -172,14 +193,33 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
}
+ /**
+ * Indicates a change in the list of Register groups e.g. after addition and removal
+ * @since 4.6
+ */
+ public static class GroupsChangedDMEvent implements IRegisters.IGroupsChangedDMEvent {
+
+ private final IContainerDMContext fGroupContainerDmc;
+
+ public GroupsChangedDMEvent(IContainerDMContext containerDMC) {
+ fGroupContainerDmc = containerDMC;
+ }
+
+ @Override
+ public IContainerDMContext getDMContext() {
+ return fGroupContainerDmc;
+ }
+ }
+
/*
* Internal control variables.
*/
private CommandFactory fCommandFactory;
- //One Group per container process
+ //One Group per container process
private final Map<IContainerDMContext, MIRegisterGroupDMC> fContainerToGroupMap = new HashMap<IContainerDMContext, MIRegisterGroupDMC>();
+
private CommandCache fRegisterNameCache; // Cache for holding the Register Names in the single Group
private CommandCache fRegisterValueCache; // Cache for holding the Register Values
@@ -267,13 +307,13 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
public void getRegisterGroupData(IRegisterGroupDMContext regGroupDmc, DataRequestMonitor<IRegisterGroupDMData> rm) {
/**
* For the GDB GDBMI implementation there is only on group. The GPR and FPU registers are grouped into
- * one set. We are going to hard wire this set as the "General Registers".
+ * one set. We are going to hard wire this set as the value of ROOT_GROUP_NAME.
*/
class RegisterGroupData implements IRegisterGroupDMData {
@Override
- public String getName() { return "General Registers"; } //$NON-NLS-1$
+ public String getName() { return ROOT_GROUP_NAME; }
@Override
- public String getDescription() { return "General Purpose and FPU Register Group"; } //$NON-NLS-1$
+ public String getDescription() { return ROOT_GROUP_DESCRIPTION; }
}
rm.setData( new RegisterGroupData() ) ;
@@ -387,7 +427,10 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
});
}
- static class RegisterData implements IRegisterDMData {
+ /**
+ * @since 4.6
+ */
+ protected static class RegisterData implements IRegisterDMData {
final private String fRegName;
final private String fRegDesc;
@@ -487,14 +530,18 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
fRegisterValueCache.reset();
}
- private void generateRegisterChangedEvent(final IRegisterDMContext dmc ) {
+ /**
+ * @since 4.6
+ */
+ protected void generateRegisterChangedEvent(IRegisterDMContext dmc ) {
getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());
- // Temporary fix for Bug 400840
+ // Fix for Bug 400840
// When one register is modified, it could affect other registers.
// To properly reflect that, we send a change for all registers.
- // We cheat since we know there is currently only one group. Once we handle
- // more groups, this may not work properly.
+ // We cheat by pretending the group has changed, since we know there is
+ // only one group.
+ // This method can be extended by group managers to propagate the event as needed
final IRegisterGroupDMContext groupDmc = DMContexts.getAncestorOfType(dmc, IRegisterGroupDMContext.class);
if (groupDmc != null) {
IRegistersChangedDMEvent event = new IRegistersChangedDMEvent() {
@@ -504,8 +551,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
};
getSession().dispatchEvent(event, getProperties());
- }
-
+ }
}
/*
@@ -524,15 +570,16 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
//Bug 418176
- //Only one group per Process (container) is supported for the time being
+ //Only one group per Process (container) is supported in the implementation of this class
MIRegisterGroupDMC registerGroup = fContainerToGroupMap.get(contDmc);
- if (registerGroup == null) {
- registerGroup = new MIRegisterGroupDMC( this , contDmc, 0 , "General Registers" ) ; //$NON-NLS-1$
- fContainerToGroupMap.put(contDmc, registerGroup);
- }
+ if (registerGroup == null) {
+ registerGroup = new MIRegisterGroupDMC(this, contDmc, 0, ROOT_GROUP_NAME);
+ fContainerToGroupMap.put(contDmc, registerGroup);
+ }
MIRegisterGroupDMC[] groupDMCs = new MIRegisterGroupDMC[] { registerGroup };
+
rm.setData(groupDMCs) ;
rm.done() ;
}
@@ -642,48 +689,35 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
* @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeRegister(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, java.lang.String, java.lang.String, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
*/
@Override
- public void writeRegister(IRegisterDMContext regCtx, final String regValue, final String formatId, final RequestMonitor rm) {
- MIRegisterGroupDMC grpDmc = DMContexts.getAncestorOfType(regCtx, MIRegisterGroupDMC.class);
- if ( grpDmc == null ) {
- rm.setStatus( new Status( IStatus.ERROR , GdbPlugin.PLUGIN_ID , INVALID_HANDLE , "RegisterGroup context not found" , null ) ) ; //$NON-NLS-1$
- rm.done();
- return;
- }
-
- final MIRegisterDMC regDmc = (MIRegisterDMC)regCtx;
- // There is only one group and its number must be 0.
- if ( grpDmc.getGroupNo() == 0 ) {
- final IExpressions exprService = getServicesTracker().getService(IExpressions.class);
- String regName = regDmc.getName();
- final IExpressionDMContext exprCtxt = exprService.createExpression(regCtx, "$" + regName); //$NON-NLS-1$
-
- final FormattedValueDMContext valueDmc = exprService.getFormattedValueContext(exprCtxt, formatId);
- exprService.getFormattedExpressionValue(
- valueDmc,
- new DataRequestMonitor<FormattedValueDMData>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- if(! regValue.equals(getData().getFormattedValue()) || ! valueDmc.getFormatID().equals(formatId)){
- exprService.writeExpression(exprCtxt, regValue, formatId, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- generateRegisterChangedEvent(regDmc);
- rm.done();
- }
- });
- }//if
- else {
- rm.done();
- }
- }//handleSuccess
- }
- );
- }
- else {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid group = " + grpDmc, null)); //$NON-NLS-1$
- rm.done();
- }
- }
+ public void writeRegister(IRegisterDMContext regCtx, final String regValue, final String formatId,
+ final RequestMonitor rm) {
+
+ assert(regCtx instanceof MIRegisterDMC);
+ final MIRegisterDMC regDmc = (MIRegisterDMC) regCtx;
+
+ final IExpressions exprService = getServicesTracker().getService(IExpressions.class);
+ String regName = regDmc.getName();
+ final IExpressionDMContext exprCtxt = exprService.createExpression(regCtx, "$" + regName); //$NON-NLS-1$
+
+ final FormattedValueDMContext valueDmc = exprService.getFormattedValueContext(exprCtxt, formatId);
+ exprService.getFormattedExpressionValue(valueDmc, new DataRequestMonitor<FormattedValueDMData>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (!regValue.equals(getData().getFormattedValue()) || !valueDmc.getFormatID().equals(formatId)) {
+ exprService.writeExpression(exprCtxt, regValue, formatId, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ generateRegisterChangedEvent(regDmc);
+ rm.done();
+ }
+ });
+ }// if
+ else {
+ rm.done();
+ }
+ }// handleSuccess
+ });
+ }
/*
* (non-Javadoc)
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.java
index 2eed408eb7..d7435c8063 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010 Ericsson and others.
+ * Copyright (c) 2010, 2014 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
@@ -8,6 +8,7 @@
* Contributors:
* Ericsson - initial API and implementation
* Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
+ * Alvaro Sanchez-Leon (Ericsson) - Support Register Groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@@ -23,6 +24,8 @@ class Messages extends NLS {
public static String Breakpoint_installation_failed;
public static String MIExpressions_NotAvailableBecauseChildOfDynamicVarobj;
public static String MIExpressions_ReturnValueAlias;
+ public static String MIRegisters_General_Registers;
+ public static String MIRegisters_General_Registers_description;
static {
// initialize resource bundle
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.properties
index 62306b7f60..ddee09bb77 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/Messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2010 Ericsson and others.
+# Copyright (c) 2010, 2014 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
@@ -8,6 +8,7 @@
# Contributors:
# Ericsson - initial API and implementation
# Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
+# Alvaro Sanchez-Leon (Ericsson) - Support Register Groups (Bug 235747)
###############################################################################
Breakpoint_attribute_detailed_problem=Breakpoint installation failed: {0}
@@ -16,3 +17,7 @@ Breakpoint_installation_failed=installation failed
MIExpressions_NotAvailableBecauseChildOfDynamicVarobj=N/A (child of pretty-printed object)
MIExpressions_ReturnValueAlias=%s returned
+
+MIRegisters_General_Registers=General Registers
+
+MIRegisters_General_Registers_description=General Purpose and FPU Register Group
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java
index 3acf3646c9..3814137d1c 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/ServiceEventWaitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2013 Ericsson and others.
+ * Copyright (c) 2007, 2014 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
@@ -9,9 +9,11 @@
* Ericsson - Initial Implementation
* Marc Khouzam (Ericsson) - Add support to receive multiple events
* Alvaro Sanchez-Leon (Ericsson) - Add filter out and wait for a given type of event
+ * Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.framework;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -96,29 +98,34 @@ public class ServiceEventWaitor<V> {
}
/**
- * Will wait and discard events that are not either of the specified type or a subtype
- * It will stop and return the first one found or exit after the specified timeout
- *
- * @param type - The parent type of an acceptable event
- * @param timeout the maximum time to wait in milliseconds to wait for a specified event
+ * Wait for events of V type for the specified amount of time
*/
- @SuppressWarnings("unchecked")
- public synchronized <T extends V> T waitForEvent(Class<T> type, int timeout) throws Exception {
+ public synchronized List<V> waitForEvents(int period) {
long startMs = System.currentTimeMillis();
- //The Specified Event received or Timeout exception will exit the loop
+ List<V> events = new ArrayList<V>();
+
+ //Timeout exception will exit the loop and return the resulting list of events
while (true) {
- int timeRemaining = (int) (timeout - (System.currentTimeMillis() - startMs));
- if (timeRemaining > 0) {
- V sevent = waitForEvent(timeRemaining);
- if (type.isAssignableFrom(sevent.getClass())) {
- return (T) sevent;
- }
+ int timeRemaining = (int) (period - (System.currentTimeMillis() - startMs));
+ if (timeRemaining > 0) {
+ V sevent;
+ try {
+ sevent = waitForEvent(timeRemaining);
+ if (sevent != null) {
+ events.add(sevent);
+ }
+ } catch (Exception e) {
+ break;
+ }
} else {
- throw new Exception("Timed out waiting for ServiceEvent: " + type.getName());
+ break;
}
}
+
+ return events;
}
+
/*
* Block until 'timeout' or the expected event occurs. The expected event is
* specified at construction time.
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/GDBPatternMatchingExpressionsTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/GDBPatternMatchingExpressionsTest.java
index efb542135a..38cbd2e669 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/GDBPatternMatchingExpressionsTest.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/GDBPatternMatchingExpressionsTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Ericsson and others.
+ * Copyright (c) 2012, 2014 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
@@ -8,6 +8,7 @@
* Contributors:
* Marc Khouzam (Ericsson) - Initial Implementation
* Marc Khouzam (Ericsson) - Tests for Pattern Matching for variables (Bug 394408)
+ * Alvaro Sanchez-Leon (Ericsson AB) - Allow user to edit register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
@@ -24,9 +25,7 @@ import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
-import org.eclipse.cdt.dsf.datamodel.CompositeDMContext;
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.IExpressions.IExpressionDMAddress;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
@@ -36,9 +35,8 @@ import org.eclipse.cdt.dsf.debug.service.IExpressions3.IExpressionDMDataExtensio
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
-import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
-import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters2;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
@@ -67,7 +65,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseTestCase {
private DsfServicesTracker fServicesTracker;
protected IMIExpressions fExpService;
- protected IRegisters fRegService;
+ protected IRegisters2 fRegService;
@Override
protected void setLaunchAttributes() {
@@ -88,7 +86,7 @@ public class GDBPatternMatchingExpressionsTest extends BaseTestCase {
fExpService = fServicesTracker.getService(IMIExpressions.class);
- fRegService = fServicesTracker.getService(IRegisters.class);
+ fRegService = fServicesTracker.getService(IRegisters2.class);
}
};
fSession.getExecutor().submit(runnable).get();
@@ -173,33 +171,27 @@ public class GDBPatternMatchingExpressionsTest extends BaseTestCase {
Query<String> query = new Query<String>() {
@Override
protected void execute(final DataRequestMonitor<String> rm) {
- fRegService.getRegisterGroups(threadDmc, new ImmediateDataRequestMonitor<IRegisterGroupDMContext[]>(rm) {
- @Override
- protected void handleSuccess() {
- fRegService.getRegisters(
- new CompositeDMContext(new IDMContext[] { getData()[0], threadDmc } ),
- new ImmediateDataRequestMonitor<IRegisterDMContext[]>(rm) {
- @Override
- protected void handleSuccess() {
- assert getData() instanceof MIRegisterDMC[];
- for (MIRegisterDMC register : (MIRegisterDMC[])getData()) {
- if (register.getName().equals(regName)) {
- final FormattedValueDMContext valueDmc = fRegService.getFormattedValueContext(register, IFormattedValues.HEX_FORMAT);
- fRegService.getFormattedExpressionValue(valueDmc, new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
- @Override
- protected void handleSuccess() {
- rm.done(getData().getFormattedValue());
- };
- });
- return;
- }
- }
- // If we get here, we didn't find the register!
- assertTrue("Invalid register: " + regName, false);
+ fRegService.getRegisters(threadDmc,
+ new ImmediateDataRequestMonitor<IRegisterDMContext[]>(rm) {
+ @Override
+ protected void handleSuccess() {
+ assert getData() instanceof MIRegisterDMC[];
+ for (MIRegisterDMC register : (MIRegisterDMC[])getData()) {
+ if (register.getName().equals(regName)) {
+ final FormattedValueDMContext valueDmc = fRegService.getFormattedValueContext(register, IFormattedValues.HEX_FORMAT);
+ fRegService.getFormattedExpressionValue(valueDmc, new ImmediateDataRequestMonitor<FormattedValueDMData>(rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.done(getData().getFormattedValue());
+ };
+ });
+ return;
}
- });
- }
- });
+ }
+ // If we get here, we didn't find the register!
+ assertTrue("Invalid register: " + regName, false);
+ }
+ });
}
};
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
index 52730259ba..2cf5d2d839 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 Ericsson and others.
+ * Copyright (c) 2009, 2014 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
@@ -8,61 +8,66 @@
* Contributors:
* Ericsson - initial API and implementation
* Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
+ * Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateCountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
-import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.CompositeDMContext;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
-import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegistersChangedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRegisters2;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
-import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.service.GDBRegisters;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
-import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
-import org.eclipse.cdt.dsf.mi.service.MIProcesses;
import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterDMC;
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.tests.dsf.gdb.framework.AsyncCompletionWaitor;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase;
+import org.eclipse.cdt.tests.dsf.gdb.framework.ServiceEventWaitor;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,13 +78,13 @@ public class MIRegistersTest extends BaseTestCase {
protected static List<String> fRegisterNames = null;
@BeforeClass
- public static void initializeGlobals() {
+ public static void initializeGlobals() {
// In case we run multiple GDB versions of this test
// in the same suite, we need to re-initialize the registers
// as they may change between GDB versions.
fRegisterNames = null;
}
-
+
protected List<String> get_X86_REGS() throws Throwable {
if (fRegisterNames == null) {
// The tests must run on different machines, so the set of registers can change.
@@ -91,8 +96,8 @@ public class MIRegistersTest extends BaseTestCase {
@Override
protected void execute(DataRequestMonitor<MIDataListRegisterNamesInfo> rm) {
IMICommandControl controlService = fServicesTracker.getService(IMICommandControl.class);
- controlService.queueCommand(
- controlService.getCommandFactory().createMIDataListRegisterNames(fContainerDmc), rm);
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(fCompositeDmc, IContainerDMContext.class);
+ controlService.queueCommand(controlService.getCommandFactory().createMIDataListRegisterNames(containerDmc), rm);
}
};
fSession.getExecutor().execute(query);
@@ -101,7 +106,7 @@ public class MIRegistersTest extends BaseTestCase {
String[] names = data.getRegisterNames();
// Remove registers with empty names since the service also
- // remove them. I don't know why GDB returns such empty names.
+ // remove them. I don't know why GDB returns such empty names.
fRegisterNames = new LinkedList<String>();
for (String name : names) {
if (!name.isEmpty()) {
@@ -111,179 +116,174 @@ public class MIRegistersTest extends BaseTestCase {
}
return fRegisterNames;
}
-
+
/*
* Path to executable
*/
private static final String EXEC_PATH = "data/launch/bin/";
+
/*
* Name of the executable
*/
private static final String EXEC_NAME = "MultiThread.exe";
private static final String SRC_NAME = "MultiThread.cc";
+ private static final String GROUP_X = "GroupX";
+ private static final String GROUP_Y = "GroupY";
+ private static final String PROPOSE_GROUP_NAME_BASE = "Group_";
+
private DsfSession fSession;
private DsfServicesTracker fServicesTracker;
- private IContainerDMContext fContainerDmc;
- private IRegisters fRegService;
- private IRunControl fRunControl;
+ private IDMContext fCompositeDmc;
+ private IRegisters2 fRegService;
+ private IRunControl fRunControl;
+ private Integer fGroupNameSuffix;
- @Override
+ @Override
public void doBeforeTest() throws Exception {
super.doBeforeTest();
-
- fSession = getGDBLaunch().getSession();
-
- Runnable runnable = new Runnable() {
- @Override
+
+ fSession = getGDBLaunch().getSession();
+
+ Runnable runnable = new Runnable() {
+ @Override
public void run() {
- // We obtain the services we need after the new
- // launch has been performed
- fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
-
- ICommandControlService commandControl = fServicesTracker.getService(ICommandControlService.class);
- IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
- IProcessDMContext procDmc = procService.createProcessContext(commandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
- fContainerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
-
- fRegService = fServicesTracker.getService(IRegisters.class);
- fRunControl = fServicesTracker.getService(IRunControl.class);
- }
- };
- fSession.getExecutor().submit(runnable).get();
+ // We obtain the services we need after the new
+ // launch has been performed
+ fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
+
+ fRegService = (IRegisters2) fServicesTracker.getService(IRegisters.class);
+ fRunControl = fServicesTracker.getService(IRunControl.class);
+ }
+ };
+
+ fSession.getExecutor().submit(runnable).get();
+
+ //resolve the execution context
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = null;
+ try {
+ frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ } catch (Throwable e1) {
+ e1.printStackTrace();
+ fail("Initialization problem");
+ }
+
+ //resolve the container context
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getInitialStoppedEvent().getDMContext(), IContainerDMContext.class);
+ //The container dmc is expected to contain the frame and container context
+ fCompositeDmc = new CompositeDMContext(new IDMContext[] { containerDmc, frameDmc });
+ fGroupNameSuffix = 0;
}
@Override
protected void setLaunchAttributes() {
super.setLaunchAttributes();
-
- setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
- EXEC_PATH + EXEC_NAME);
- }
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME);
+ }
+
+
@Override
public void doAfterTest() throws Exception {
super.doAfterTest();
-
+
fServicesTracker.dispose();
fRegService = null;
}
- /*
- * This is a common support method which gets the Register Group Information
- * and verifies it.
- */
- private IRegisterGroupDMContext getRegisterGroup() throws Throwable {
- final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
+ /*
+ * This is a common support method which gets the Register Group Information from target
+ */
+ private IRegisterGroupDMContext getTargetRegisterGroup() throws Throwable {
+ //Get all the registers from the Container (Process)
+ IRegisterDMContext[] registers = getRegisters(fCompositeDmc);
+ assertTrue(registers.length > 0);
+
+ //Get the register group from any of the register contexts
+ IRegisterGroupDMContext regGroupsDMC = DMContexts.getAncestorOfType(registers[0], IRegisterGroupDMContext.class);
+ assertNotNull(regGroupsDMC);
- final DataRequestMonitor<IRegisterGroupDMContext[]> regGroupDone =
- new DataRequestMonitor<IRegisterGroupDMContext[]>(fRegService.getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- if (isSuccess()) {
- fWait.setReturnInfo(getData());
- }
-
- fWait.waitFinished(getStatus());
- }
- };
-
- fRegService.getExecutor().submit(new Runnable() {
- @Override
- public void run() {
- fRegService.getRegisterGroups(fContainerDmc, regGroupDone);
- }
- });
-
- fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
- assertTrue(fWait.getMessage(), fWait.isOK());
+ return regGroupsDMC;
+ }
- IRegisterGroupDMContext[] regGroupsDMCs = (IRegisterGroupDMContext[])fWait.getReturnInfo();
- assertTrue("There was more than one register group (" + regGroupsDMCs.length + ")", //$NON-NLS-1$
- regGroupsDMCs.length == 1 );
- fWait.waitReset();
-
- return(regGroupsDMCs[0]);
- }
+ /*
+ * This is a common support method which gets the Registers names.
+ */
+ private IRegisterDMContext[] getAllRegisters(final IFrameDMContext frameDmc) throws Throwable {
+
+ Query<IRegisterDMContext[]> queryRegisters = new Query<IRegisterDMContext[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterDMContext[]> rm) {
+ fRegService.getRegisters(new CompositeDMContext(new IDMContext[] { fCompositeDmc, frameDmc }), rm);
+ }
+ };
+
+ fSession.getExecutor().execute(queryRegisters);
+
+ IRegisterDMContext[] regContexts = queryRegisters.get(500, TimeUnit.MILLISECONDS);
+
+ assertEquals("Wrong number of registers", get_X86_REGS().size(), regContexts.length);
+
+ return regContexts;
+ }
/*
- * This is a common support method which gets the Registers names.
+ * Get the Registers for the specified composite context
*/
-
- private IRegisterDMContext[] getRegisters(final IFrameDMContext frameDmc) throws Throwable {
- final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
- final IRegisterGroupDMContext regGroupsDMC = getRegisterGroup();
+ private IRegisterDMContext[] getRegisters(final IDMContext dmc) throws Throwable {
+
+ Query<IRegisterDMContext[]> queryRegistersDmc = new Query<IRegisterDMContext[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterDMContext[]> rm) {
+ fRegService.getRegisters(dmc, rm);
+ }
+ };
- fRegService.getExecutor().submit(new Runnable() {
- @Override
- public void run() {
- fRegService.getRegisters(
- new CompositeDMContext(new IDMContext[] { regGroupsDMC, frameDmc} ),
- new DataRequestMonitor<IRegisterDMContext[]>(fRegService.getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- if (isSuccess()) {
- fWait.setReturnInfo(getData());
- }
-
- fWait.waitFinished(getStatus());
- }
- });
- }
- });
-
- fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
- assertTrue(fWait.getMessage(), fWait.isOK());
-
- IRegisterDMContext[] regContexts = (IRegisterDMContext[]) fWait.getReturnInfo();
-
- fWait.waitReset();
-
- assertEquals("Wrong number of registers", get_X86_REGS().size(), regContexts.length);
+ fRegService.getExecutor().submit(queryRegistersDmc);
+ IRegisterDMContext[] regContexts = queryRegistersDmc.get(500, TimeUnit.MILLISECONDS);
return(regContexts);
}
-
- /*************************************************************************
- *
- * The tests for the register service.
- *
- *************************************************************************/
-
- @Test
- public void getRegisterGroups() throws Throwable {
- final IRegisterGroupDMContext regGroupsDMC = getRegisterGroup();
-
- Query<IRegisterGroupDMData> query = new Query<IRegisterGroupDMData>() {
- @Override
- protected void execute(DataRequestMonitor<IRegisterGroupDMData> rm) {
- fRegService.getRegisterGroupData(regGroupsDMC, rm);
- }
- };
- fSession.getExecutor().execute(query);
-
- IRegisterGroupDMData data = query.get();
+
+ /*
+ * This is a common support method which gets the Register context of root group over the specified frame context
+ */
+ private IRegisterDMContext[] getTargetRegisters(final IFrameDMContext frameDmc) throws Throwable {
+ IRegisterDMContext[] regContexts = getRegisters(new CompositeDMContext(new IDMContext[] { fCompositeDmc, frameDmc}));
+ assertEquals("Wrong number of registers", get_X86_REGS().size(), regContexts.length);
- assertTrue("The name of the main group should be: General Registers instead of: " +
- data.getName(),
- data.getName().equals("General Registers"));
- }
-
- @Test
- public void getRegistersLength() throws Throwable {
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
- assertEquals("Wrong number of registers", get_X86_REGS().size(), regDMCs.length);
+ return regContexts;
}
-
- @Test
- public void getRegisters() throws Throwable {
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
- List<String> regNames = get_X86_REGS();
+
+ /*************************************************************************
+ *
+ * The tests for the register service.
+ *
+ *************************************************************************/
+ @Test
+ public void resolveTargetRegisterGroup() throws Throwable {
+ final IRegisterGroupDMContext regGroupsDMC = getTargetRegisterGroup();
+ IRegisterGroupDMData data = getRegisterGroupData(regGroupsDMC);
+
+ assertTrue("The name of the main group should be: General Registers instead of: " + data.getName(), data.getName().equals("General Registers"));
+ }
+
+ @Test
+ public void resolveTargetRegistersLength() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
+ assertEquals("Wrong number of registers", get_X86_REGS().size(), regDMCs.length);
+ }
+
+ @Test
+ public void getRegisters() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
+ List<String> regNames = get_X86_REGS();
IRegisterDMData[] datas = getRegistersData(regDMCs);
@@ -295,113 +295,99 @@ public class MIRegistersTest extends BaseTestCase {
private IRegisterDMData[] getRegistersData(final IRegisterDMContext[] regDMCs) throws InterruptedException, ExecutionException {
- Query<IRegisterDMData[]> query = new Query<IRegisterDMData[]>() {
- @Override
- protected void execute(DataRequestMonitor<IRegisterDMData[]> rm) {
- final IRegisterDMData[] datas = new IRegisterDMData[regDMCs.length];
- rm.setData(datas);
- final CountingRequestMonitor countingRm = new ImmediateCountingRequestMonitor(rm);
- countingRm.setDoneCount(regDMCs.length);
- for (int i = 0; i < regDMCs.length; i++) {
- final int index = i;
- fRegService.getRegisterData(
- regDMCs[index],
- new ImmediateDataRequestMonitor<IRegisterDMData>(countingRm) {
- @Override
- protected void handleSuccess() {
- datas[index] = getData();
- countingRm.done();
- }
- });
- }
-
- }
- };
-
- fSession.getExecutor().execute(query);
-
+ Query<IRegisterDMData[]> query = new Query<IRegisterDMData[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterDMData[]> rm) {
+ final IRegisterDMData[] datas = new IRegisterDMData[regDMCs.length];
+ rm.setData(datas);
+ final CountingRequestMonitor countingRm = new ImmediateCountingRequestMonitor(rm);
+ countingRm.setDoneCount(regDMCs.length);
+ for (int i = 0; i < regDMCs.length; i++) {
+ final int index = i;
+ fRegService.getRegisterData(regDMCs[index], new ImmediateDataRequestMonitor<IRegisterDMData>(countingRm) {
+ @Override
+ protected void handleSuccess() {
+ datas[index] = getData();
+ countingRm.done();
+ }
+ });
+ }
+
+ }
+ };
+
+ fSession.getExecutor().execute(query);
+
return query.get();
}
private String getModelDataForRegisterDataValue(IFrameDMContext frameDmc, String format, int regNo) throws Throwable {
- final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
-
- final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
- final FormattedValueDMContext valueDmc = fRegService.getFormattedValueContext(regDMCs[regNo], format);
-
- final DataRequestMonitor<FormattedValueDMData> regRm =
- new DataRequestMonitor<FormattedValueDMData>(fRegService.getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- if (isSuccess()) {
- wait.setReturnInfo(getData());
- }
-
- wait.waitFinished(getStatus());
- }
- };
-
- fRegService.getExecutor().submit(new Runnable() {
- @Override
- public void run() {
- fRegService.getFormattedExpressionValue(valueDmc, regRm);
- }
- });
-
- wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
- assertTrue(wait.getMessage(), wait.isOK());
+ final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
+ return getModelDataForRegisterDataValue(regDMCs[regNo], format);
+ }
-
- FormattedValueDMData data = (FormattedValueDMData)wait.getReturnInfo();
- return data.getFormattedValue();
- }
+ private String getModelDataForRegisterDataValue(IRegisterDMContext registerDmc, String format) throws Throwable {
+ final FormattedValueDMContext valueDmc = fRegService.getFormattedValueContext(registerDmc, format);
- @Test
- public void getModelDataForRegisterDataValueInDifferentNumberFormats() throws Throwable {
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.NATURAL_FORMAT, 0);
- try {
- Long.parseLong(val);
- } catch (NumberFormatException e) {
- assertTrue("Register Value is not in NATURAL_FORMAT: " + val, false);
- }
+ Query<FormattedValueDMData> queryFormattedData = new Query<FormattedValueDMData>() {
+ @Override
+ protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
+ fRegService.getFormattedExpressionValue(valueDmc, rm);
+ }
+ };
- val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.HEX_FORMAT, 0);
- assertTrue("Register Value is not in HEX_FORMAT: " + val, val.startsWith("0x"));
- try {
- Long.parseLong(val.substring(2), 16);
- } catch (NumberFormatException e) {
- assertTrue("Register Value is not in HEX_FORMAT: " + val, false);
- }
+ fRegService.getExecutor().submit(queryFormattedData);
- val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.BINARY_FORMAT, 0);
- try {
- Long.parseLong(val, 2);
- } catch (NumberFormatException e) {
- assertTrue("Register Value is not in BINARY_FORMAT: " + val, false);
- }
+ FormattedValueDMData data = queryFormattedData.get(500, TimeUnit.MILLISECONDS);
+ return data.getFormattedValue();
+ }
- val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.DECIMAL_FORMAT , 0);
- try {
- Long.parseLong(val);
- } catch (NumberFormatException e) {
- assertTrue("Register Value is not in DECIMAL_FORMAT: " + val, false);
- }
- val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.OCTAL_FORMAT, 0);
- assertTrue("Register Value is not in OCTAL_FORMAT: " + val, val.startsWith("0"));
- try {
- Long.parseLong(val.substring(1), 8);
- } catch (NumberFormatException e) {
- assertTrue("Register Value is not in OCTAL_FORMAT: " + val, false);
- }
- }
+ @Test
+ public void getModelDataForRegisterDataValueInDifferentNumberFormats() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.NATURAL_FORMAT, 0);
+ try {
+ Long.parseLong(val);
+ } catch (NumberFormatException e) {
+ assertTrue("Register Value is not in NATURAL_FORMAT: " + val, false);
+ }
- @Test
- public void compareRegisterForMultipleExecutionContexts() throws Throwable {
+ val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.HEX_FORMAT, 0);
+ assertTrue("Register Value is not in HEX_FORMAT: " + val, val.startsWith("0x"));
+ try {
+ Long.parseLong(val.substring(2), 16);
+ } catch (NumberFormatException e) {
+ assertTrue("Register Value is not in HEX_FORMAT: " + val, false);
+ }
+
+ val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.BINARY_FORMAT, 0);
+ try {
+ Long.parseLong(val, 2);
+ } catch (NumberFormatException e) {
+ assertTrue("Register Value is not in BINARY_FORMAT: " + val, false);
+ }
+ val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.DECIMAL_FORMAT, 0);
+ try {
+ Long.parseLong(val);
+ } catch (NumberFormatException e) {
+ assertTrue("Register Value is not in DECIMAL_FORMAT: " + val, false);
+ }
+
+ val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.OCTAL_FORMAT, 0);
+ assertTrue("Register Value is not in OCTAL_FORMAT: " + val, val.startsWith("0"));
+ try {
+ Long.parseLong(val.substring(1), 8);
+ } catch (NumberFormatException e) {
+ assertTrue("Register Value is not in OCTAL_FORMAT: " + val, false);
+ }
+ }
+
+ @Test
+ public void compareRegisterForMultipleExecutionContexts() throws Throwable {
// Run past the line that creates a thread and past the sleep that
// follows it. This is a bit tricky because the code that creates the
// thread is conditional depending on environment. Run to the printf
@@ -409,161 +395,151 @@ public class MIRegistersTest extends BaseTestCase {
// non-common code (but same number of lines)
SyncUtil.runToLine(SRC_NAME, MIRunControlTest.LINE_MAIN_PRINTF);
- // Because the program is about to go multi-threaded, we have to select the thread
- // we want to keep stepping. If we don't, we will ask GDB to step the entire process
- // which is not what we want. We can fetch the thread from the stopped event
- // but we should do that before the second thread is created, to be sure the stopped
- // event is for the main thread.
- MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_OVER); // over the printf
- SyncUtil.step(stoppedEvent.getDMContext(), StepType.STEP_OVER); // over the create-thread call
- stoppedEvent = SyncUtil.step(stoppedEvent.getDMContext(), StepType.STEP_OVER, TestsPlugin.massageTimeout(2000)); // over the one second sleep
-
- // Get the thread IDs
- final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(stoppedEvent.getDMContext(), IContainerDMContext.class);
-
- final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
- final DataRequestMonitor<IExecutionDMContext[]> drm =
- new DataRequestMonitor<IExecutionDMContext[]>(fRegService.getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- if (isSuccess()) {
- wait.setReturnInfo(getData());
- }
- wait.waitFinished(getStatus());
- }
- };
-
- fRegService.getExecutor().submit(new Runnable() {
- @Override
- public void run() {
- fRunControl.getExecutionContexts(containerDmc, drm);
- }
- });
- wait.waitUntilDone(TestsPlugin.massageTimeout(5000));
- Assert.assertTrue(wait.getMessage(), wait.isOK());
+ // Because the program is about to go multi-threaded, we have to select the thread we want to keep stepping. If we don't, we will ask GDB to step
+ // the entire process which is not what we want. We can fetch the thread from the stopped event but we should do that before the second thread is
+ // created, to be sure the stopped event is for the main thread.
+ MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_OVER); // over the printf
+ SyncUtil.step(stoppedEvent.getDMContext(), StepType.STEP_OVER); // over the create-thread call
+ stoppedEvent = SyncUtil.step(stoppedEvent.getDMContext(), StepType.STEP_OVER, TestsPlugin.massageTimeout(2000)); // over the one second sleep
+
+ // Get the thread IDs
+ final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(stoppedEvent.getDMContext(), IContainerDMContext.class);
+
+ Query<IExecutionDMContext[]> queryExecutionContexts = new Query<IExecutionDMContext[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IExecutionDMContext[]> rm) {
+ fRunControl.getExecutionContexts(containerDmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryExecutionContexts);
- IExecutionDMContext[] ctxts = (IExecutionDMContext[])wait.getReturnInfo();
- wait.waitReset();
+ IExecutionDMContext[] ctxts = queryExecutionContexts.get(500, TimeUnit.MILLISECONDS);
Assert.assertNotNull(ctxts);
Assert.assertTrue(ctxts.length > 1);
-
- int tid1 = ((IMIExecutionDMContext)ctxts[0]).getThreadId();
- int tid2 = ((IMIExecutionDMContext)ctxts[1]).getThreadId();
-
- // Get execution context to thread 2
- IExecutionDMContext execDmc = SyncUtil.createExecutionContext(containerDmc, tid2);
- IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(execDmc, 0);
-
- String thread2RegVal0 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 0);
- String thread2RegVal1 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 1);
- String thread2RegVal2 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 2);
- String thread2RegVal3 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 3);
- String thread2RegVal4 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 4);
- String thread2RegVal5 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 5);
-
- // Get execution context to thread 1
- execDmc = SyncUtil.createExecutionContext(containerDmc, tid1);
- IFrameDMContext frameDmc1 = SyncUtil.getStackFrame(execDmc, 0);
- getModelDataForRegisterDataValue(frameDmc1, IFormattedValues.NATURAL_FORMAT, 0);
-
- // Re-set the execution context to 2 and Fetch from the Cache
- String dupliThread2RegVal0 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 0);
- String dupliThread2RegVal1 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 1);
- String dupliThread2RegVal2 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 2);
- String dupliThread2RegVal3 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 3);
- String dupliThread2RegVal4 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 4);
- String dupliThread2RegVal5= getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 5);
-
- // If Values not equal , then context haven't been re-set properly
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal0.equals(dupliThread2RegVal0));
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal1.equals(dupliThread2RegVal1));
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal2.equals(dupliThread2RegVal2));
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal3.equals(dupliThread2RegVal3));
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal4.equals(dupliThread2RegVal4));
- assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal5.equals(dupliThread2RegVal5));
-
- }
-
- private void writeRegister(IFrameDMContext frameDmc, final int regIndex, final String regValue, final String formatId) throws Throwable {
- final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
-
- final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
- fRegService.getExecutor().submit(new Runnable() {
- @Override
- public void run() {
- fRegService.writeRegister(
- regDMCs[regIndex],
- regValue, formatId,
- new RequestMonitor(fRegService.getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- fWait.waitFinished(getStatus());
- }
- });
+ int tid1 = ((IMIExecutionDMContext) ctxts[0]).getThreadId();
+ int tid2 = ((IMIExecutionDMContext) ctxts[1]).getThreadId();
+
+ // Get execution context to thread 2
+ IExecutionDMContext execDmc = SyncUtil.createExecutionContext(containerDmc, tid2);
+ IFrameDMContext frameDmc2 = SyncUtil.getStackFrame(execDmc, 0);
+
+ String thread2RegVal0 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 0);
+ String thread2RegVal1 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 1);
+ String thread2RegVal2 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 2);
+ String thread2RegVal3 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 3);
+ String thread2RegVal4 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 4);
+ String thread2RegVal5 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 5);
+
+ // Get execution context to thread 1
+ execDmc = SyncUtil.createExecutionContext(containerDmc, tid1);
+ IFrameDMContext frameDmc1 = SyncUtil.getStackFrame(execDmc, 0);
+
+ getModelDataForRegisterDataValue(frameDmc1, IFormattedValues.NATURAL_FORMAT, 0);
+
+ // Re-set the execution context to 2 and Fetch from the Cache
+ String dupliThread2RegVal0 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 0);
+ String dupliThread2RegVal1 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 1);
+ String dupliThread2RegVal2 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 2);
+ String dupliThread2RegVal3 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 3);
+ String dupliThread2RegVal4 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 4);
+ String dupliThread2RegVal5 = getModelDataForRegisterDataValue(frameDmc2, IFormattedValues.NATURAL_FORMAT, 5);
+
+ // If Values not equal , then context haven't been re-set properly
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal0.equals(dupliThread2RegVal0));
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal1.equals(dupliThread2RegVal1));
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal2.equals(dupliThread2RegVal2));
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal3.equals(dupliThread2RegVal3));
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal4.equals(dupliThread2RegVal4));
+ assertTrue("Multiple context not working. Execution Context is not reset to 2", thread2RegVal5.equals(dupliThread2RegVal5));
+
+ }
+
+ private void writeRegister(IFrameDMContext frameDmc, final int regIndex, final String regValue, final String formatId) throws Throwable {
+ final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
+ writeRegister(regDMCs[regIndex], regValue, formatId);
+ }
+
+ private void writeRegister(final IRegisterDMContext registerDmc, final String regValue, final String formatId) throws Throwable {
+ Query<Object> queryAction = new Query<Object>() {
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ fRegService.writeRegister(registerDmc, regValue, formatId, rm);
}
- });
+ };
- fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
- fWait.waitReset();
- }
-
+ fRegService.getExecutor().submit(queryAction);
+ queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Waits for IRegistersChangedDMEvent(s) during a time interval, collects them and returns them after timeout
+ */
+ private List<IRegistersChangedDMEvent> writeRegisterWaitNotication(final IRegisterDMContext registerDmc, final String regValue, final String formatId)
+ throws Throwable {
+ ServiceEventWaitor<IRegistersChangedDMEvent> eventWaitor =
+ new ServiceEventWaitor<IRegistersChangedDMEvent>(fSession, IRegistersChangedDMEvent.class);
- @Test
- public void writeRegisterNaturalFormat() throws Throwable{
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- String regValue = "10";
- int regIndex = 3;
- writeRegister(frameDmc, 3, regValue, IFormattedValues.NATURAL_FORMAT);
- String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.NATURAL_FORMAT, regIndex);
- assertTrue("Failed writing register. New value should have been " + regValue, regValue.equals(val));
- }
-
- @Test
- public void writeRegisterHEXFormat() throws Throwable{
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- String regValue = "0x10";
- int regIndex = 3;
- writeRegister(frameDmc, 3, regValue, IFormattedValues.HEX_FORMAT);
- String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.HEX_FORMAT, regIndex);
- assertTrue("Failed writing register. New value should have been " + regValue, regValue.equals(val));
- }
-
- @Test
- @Ignore
- public void writeRegisterBinaryFormat() throws Throwable{
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- //String regValue = "0100101001";
- String regValue = "10";
- int regIndex = 3;
- writeRegister(frameDmc, 3, regValue, IFormattedValues.BINARY_FORMAT);
- String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.BINARY_FORMAT, regIndex);
- assertTrue("Failed writing register. New value should have been " + regValue + " instead of " + val, regValue.equals(val));
- }
+ writeRegister(registerDmc, regValue, formatId);
+
+ return eventWaitor.waitForEvents(TestsPlugin.massageTimeout(3000));
+ }
+
+
+ @Test
+ public void writeRegisterNaturalFormat() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ String regValue = "10";
+ int regIndex = 3;
+ writeRegister(frameDmc, 3, regValue, IFormattedValues.NATURAL_FORMAT);
+ String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.NATURAL_FORMAT, regIndex);
+ assertTrue("Failed writing register. New value should have been " + regValue, regValue.equals(val));
+ }
+
+ @Test
+ public void writeRegisterHEXFormat() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ String regValue = "0x10";
+ int regIndex = 3;
+ writeRegister(frameDmc, 3, regValue, IFormattedValues.HEX_FORMAT);
+ String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.HEX_FORMAT, regIndex);
+ assertTrue("Failed writing register. New value should have been " + regValue, regValue.equals(val));
+ }
+
+ @Test
+ public void writeRegisterBinaryFormat() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ String regValue = "100101001";
+ int regIndex = 3;
+ writeRegister(frameDmc, 3, regValue, IFormattedValues.BINARY_FORMAT);
+ String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.BINARY_FORMAT, regIndex);
+ assertTrue("Failed writing register. New value should have been " + regValue + " instead of " + val, regValue.equals(val));
+ }
+
+ @Test
+ public void writeRegisterOctalFormat() throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ // String regValue = "10";
+ String regValue = "012";
+ int regIndex = 3;
+ writeRegister(frameDmc, 3, regValue, IFormattedValues.OCTAL_FORMAT);
+ String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.OCTAL_FORMAT, regIndex);
+ assertTrue("Failed writing register. New value should have been " + regValue + "instead of " + val, regValue.equals(val));
+ }
- @Test
- public void writeRegisterOctalFormat() throws Throwable{
- MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
- IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- //String regValue = "10";
- String regValue = "012";
- int regIndex = 3;
- writeRegister(frameDmc, 3, regValue, IFormattedValues.OCTAL_FORMAT);
- String val = getModelDataForRegisterDataValue(frameDmc, IFormattedValues.OCTAL_FORMAT, regIndex);
- assertTrue("Failed writing register. New value should have been " + regValue + "instead of " + val, regValue.equals(val));
- }
-
/**
* This test validates retrieval of different values for the same register used on different frames
*/
@Test
public void frameSpecificValues() throws Throwable {
- // Step to a multi-level stack level to be able to test different stack frames
+ // Step to a multi-level stack to be able to test different stack frames
SyncUtil.runToLocation("PrintHello");
MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_OVER);
int depth = SyncUtil.getStackDepth(stoppedEvent.getDMContext());
@@ -577,14 +553,14 @@ public class MIRegistersTest extends BaseTestCase {
// Get the stack pointer value for frame0
IFrameDMContext frame0 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
- IRegisterDMContext[] registers_f0 = getRegisters(frame0);
+ IRegisterDMContext[] registers_f0 = getTargetRegisters(frame0);
MIRegisterDMC sp_reg_f0 = (MIRegisterDMC) findStackPointerRegister(sp_name, registers_f0);
assertNotNull(sp_reg_f0);
String sp_f0_str = getModelDataForRegisterDataValue(frame0, IFormattedValues.HEX_FORMAT, sp_reg_f0.getRegNo());
// Get the stack pointer value for frame1
IFrameDMContext frame1 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1);
- IRegisterDMContext[] registers_f1 = getRegisters(frame1);
+ IRegisterDMContext[] registers_f1 = getTargetRegisters(frame1);
MIRegisterDMC sp_reg_f1 = (MIRegisterDMC) findStackPointerRegister(sp_name, registers_f1);
assertNotNull(sp_reg_f1);
String sp_f1_str = getModelDataForRegisterDataValue(frame1, IFormattedValues.HEX_FORMAT, sp_reg_f1.getRegNo());
@@ -629,4 +605,760 @@ public class MIRegistersTest extends BaseTestCase {
return null;
}
+
+ @Test
+ public void getRegisterGroupsData() throws Throwable {
+ int grpsIncrement = 3;
+
+ //Group name to Group description
+ Map<String, String> groupNameToDescMap = new HashMap<>();
+ groupNameToDescMap.put("Group_1", "");
+ groupNameToDescMap.put("Group_2", "");
+ groupNameToDescMap.put("Group_3", "");
+ groupNameToDescMap.put("General Registers", "General Purpose and FPU Register Group");
+
+ //Tracking groups found
+ Set<String> groupsFound = new HashSet<>();
+
+ addRegisterGroups(grpsIncrement);
+ final IRegisterDMContext[] regInGroup = getRegisters(0, 4);
+
+ IRegisterGroupDMData[] groupsData = getRegisterGroupsData(regInGroup[0]);
+ //increment + root
+ assertTrue(groupsData.length == grpsIncrement + 1);
+ for (IRegisterGroupDMData grpData: groupsData) {
+ // Validate group name
+ assertTrue(groupNameToDescMap.containsKey(grpData.getName()));
+ String grpDataDesc = grpData.getDescription();
+ String expectedName = groupNameToDescMap.get(grpData.getName());
+
+ //Validate group description
+ assertTrue(grpDataDesc.equals(expectedName));
+ groupsFound.add(grpData.getName());
+ }
+
+ //Make sure all expected groups were found
+ assertTrue(groupsFound.size() == groupNameToDescMap.size());
+ }
+
+ @Test
+ public void canAddRegisterGroup() throws Throwable {
+ // only root group expected
+ final IRegisterGroupDMContext[] groups = getRegisterGroups(1);
+ assertTrue("Unexpected groups present, only root was expected", groups.length == 1);
+ assertTrue("Can not Add register groups", canAddRegisterGroup(groups[0]));
+ }
+
+ @Test
+ public void canNotEditRootRegisterGroup() throws Throwable {
+ // only root group expected
+ final IRegisterGroupDMContext[] groups = getRegisterGroups(1);
+ assertTrue("Unexpected groups present, only root was expected", groups.length == 1);
+
+ assertFalse("Not expected to allow the editing of the root register group", canEditRegisterGroup(groups[0]));
+ }
+
+ @Test
+ public void canNotEditUnknownRegisterGroup() throws Throwable {
+ // only root group expected
+ final IRegisterGroupDMContext group = new IRegisterGroupDMContext() {
+
+ @Override
+ public String getSessionId() {
+ return "session";
+ }
+
+ @Override
+ public IDMContext[] getParents() {
+ return new IDMContext[0];
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return null;
+ }
+ };
+
+ assertFalse("Not expected to allow editing of a non registered group", canEditRegisterGroup(group));
+ }
+
+ @Test
+ public void canEditRegisterGroup() throws Throwable {
+ // only root group expected
+ final IRegisterGroupDMContext[] groups = getRegisterGroups(1);
+ assertTrue("Unexpected groups present, only root was expected", groups.length == 1);
+
+ IRegisterGroupDMContext group = addDefaultUserGroup();
+ assertTrue("Was not allowed to edit register group", canEditRegisterGroup(group));
+ }
+
+ /**
+ * @throws Throwable
+ */
+ @Test
+ public void addRegisterGroups() throws Throwable {
+ // Define a subset of registers to create a register group (from, to)
+ final IRegisterDMContext[] regInGroup = getRegisters(0, 4);
+
+ // Adding three groups with default names
+ String groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+ // Resolve the new group's sequence number from the pattern "Group_sequenceN"
+ int starting_sequence = resolveGroupNameSequence(groupName);
+
+ groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+
+ groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+
+ // Retrieve the existing groups, expected and validated to root + 3
+ IRegisterGroupDMContext[] groups = getRegisterGroups(4);
+
+ // The groups are returned in reversed order to present latest created
+ // first i.e. index 0
+ // The newest group shall be at the top then i.e. 0
+
+ //Add a valid execution context to resolve the register values
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regInGroup[0], IFrameDMContext.class);
+ CompositeDMContext compositeDmc = new CompositeDMContext(new IDMContext[]{frameDmc, groups[0]});
+ IRegisterDMContext[] readRegisters = getRegisters(compositeDmc);
+
+ // Same order, same data and same values are expected, although different instances to different parents
+ assertTrue(sameData(regInGroup, readRegisters, false));
+
+ // Assert the last created group name
+ IRegisterGroupDMData groupData = getRegisterGroupData(groups[0]);
+ // 2 additional groups after creation of the base group in this test case
+ assertEquals("Group_" + (starting_sequence + 2), groupData.getName());
+ }
+
+ @Test
+ public void editRegisterGroup() throws Throwable {
+ // Get Register Groups
+ IRegisterGroupDMContext[] groups = getRegisterGroups(1);
+ assertEquals("unexpected groups present", 1, groups.length);
+
+ IRegisterGroupDMContext group = addDefaultUserGroup();
+
+ IRegisterDMContext[] origRegisters = getRegisters(group);
+
+ // Assert the default group name
+ IRegisterGroupDMData groupData = getRegisterGroupData(group);
+ assertEquals(GROUP_X, groupData.getName());
+
+ // Registers to associate to exiting default group
+ IRegisterDMContext[] newRegisters = getRegisters(5, 9);
+
+ // A different set of registers being assigned to the group
+ assertFalse((sameData(origRegisters, newRegisters, false)));
+
+ // Modify the name and associated registers of the default group
+ editGroup(group, GROUP_Y, newRegisters);
+
+ groupData = getRegisterGroupData(group);
+ assertEquals(GROUP_Y, groupData.getName());
+
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(newRegisters[0], IFrameDMContext.class);
+
+ //Read the context with a valid execution context
+ CompositeDMContext compositeDmc = new CompositeDMContext(new IDMContext[]{group, frameDmc});
+ IRegisterDMContext[] readRegisters = getRegisters(compositeDmc);
+
+ //Same data but not from the same parent group, newRegisters from root, readRegisters from GroupY
+ assertTrue(sameData(newRegisters, readRegisters, false));
+
+ }
+
+ @Test
+ public void canRemoveRegisterGroup() throws Throwable {
+ // only root group expected
+ IRegisterGroupDMContext[] groups = getRegisterGroups(1);
+ assertFalse("Removal of root register group shall not be allowed", canRemoveRegisterGroups(groups));
+
+ //Add another two groups
+ // Define a subset of registers to create a register group (from, to)
+ final IRegisterDMContext[] regInGroup = getRegisters(0, 4);
+
+ // Adding three groups with default names
+ String groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+
+ groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+
+ groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+
+ // Retrieve the existing groups, expected and validated to root + 3
+ groups = getRegisterGroups(4);
+
+ //Remove the root group from the list, so the remaining can be validated
+ //as can be removed
+ groups = Arrays.copyOfRange(groups, 0, groups.length-1);
+ assertTrue("Not allowing removal of groups", canRemoveRegisterGroups(groups));
+
+ //remove the non root groups and validate the result
+ removeGroups(groups);
+ groups = getRegisterGroups(1);
+ }
+
+ @Test
+ public void removeRegisterGroups() throws Throwable {
+ int grpsIncrement = 3;
+ addRegisterGroups(grpsIncrement);
+
+ // Retrieve the existing groups, expected and validated to 1 root + 3
+ IRegisterGroupDMContext[] groups = getRegisterGroups(1 + grpsIncrement);
+
+ // remove one and assert the new size
+ IRegisterGroupDMContext[] remGroups = new IRegisterGroupDMContext[] { groups[0] };
+ removeGroups(remGroups);
+ getRegisterGroups(grpsIncrement); // assert this to root + 2
+
+ // remove two more and assert the new size
+ remGroups = new IRegisterGroupDMContext[] { groups[1], groups[2] };
+ removeGroups(remGroups);
+ getRegisterGroups(1); // assert this to only one i.e. root
+
+ // attempt to remove root -- Shall not be allowed
+ remGroups = new IRegisterGroupDMContext[] { groups[3] };
+ removeGroups(remGroups);
+ getRegisterGroups(1); // assert this to only one i.e. root
+ }
+
+ /**
+ * The root group shall not be deleted i.e. ignore and preserved
+ */
+ @Test
+ public void removeRegisterGroupsWithRoot() throws Throwable {
+ int grpsIncrement = 3;
+ addRegisterGroups(grpsIncrement);
+
+ // Retrieve the existing groups, expected and validated to 1 root + 3
+ IRegisterGroupDMContext[] groups = getRegisterGroups(1 + grpsIncrement);
+
+ // Attempt to remove all i.e. root + user defined register groups
+ removeGroups(groups);
+ getRegisterGroups(1); // assert root is preserved
+ }
+
+
+ @Test
+ public void canRestoreRegisterGroups() throws Throwable {
+ int grpsIncrement = 3;
+ addRegisterGroups(grpsIncrement);
+ //Always able to restore to default
+ assertTrue(canRestoreDefaultGroups());
+ }
+
+ @Test
+ public void restoreRegisterGroups() throws Throwable {
+ int grpsIncrement = 3;
+ addRegisterGroups(grpsIncrement);
+
+ restoreDefaultGroups();
+
+ // assert all groups are gone except root
+ getRegisterGroups(1);
+ }
+
+ @Test
+ public void getRegisterNames() throws Throwable {
+ int grpsIncrement = 2;
+ addRegisterGroups(grpsIncrement);
+ IRegisterGroupDMContext[] groups = getRegisterGroups(3); // root +
+ // increment
+
+ IRegisterDMContext[] regDmcs1 = getRegisters(groups[0]);
+ IRegisterDMContext[] regDmcs2 = getRegisters(groups[1]);
+
+ IRegisterDMData[] regNames1 = getRegistersData(regDmcs1);
+ IRegisterDMData[] regNames2 = getRegistersData(regDmcs2);
+
+ // assert the register names match on both groups
+ assertTrue(sameRegisterNames(regNames1, regNames2));
+ }
+
+ @Test
+ public void saveAndReadRegisterGroupData() throws Throwable {
+ //Only the default group is expected
+ int starting_sequence = 0;
+
+ int grpsIncrement = 2;
+ addRegisterGroups(grpsIncrement);
+ getRegisterGroups(3); // root + 2
+
+ //The two steps below would ideally use a shutdown and the start of a new launch configuration within the same case.
+ //However the approach below accomplishes verification of saving and reading with out over complicating the current base test case structure.
+
+ //trigger groups saving
+ saveRegGroups();
+
+ //trigger group reading from launch configuration
+ resetRegService();
+
+ IRegisterGroupDMContext[] groups = getRegisterGroups(3); // root + 2
+ // Assert the last created group name
+ IRegisterGroupDMData groupData = getRegisterGroupData(groups[0]);
+ // 2 additional groups after creation of the base group in this test case
+ assertEquals("Group_" + (starting_sequence + grpsIncrement), groupData.getName());
+ }
+
+ /**
+ * All groups shall be able to write / update register values, These new value shall be propagated to any other
+ * group(s) containing this register
+ */
+ @Test
+ public void writeRegisterFromUserGroup() throws Throwable {
+ // Define a subset of registers common to other register groups
+ // indexes (from, to)
+ final IRegisterDMContext[] regInRootGroup = getRegisters(0, 4);
+ String oirigVal = getModelDataForRegisterDataValue(regInRootGroup[0], IFormattedValues.NATURAL_FORMAT);
+
+ // Get a handle to the execution contexts, same frame execution context for all actions
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regInRootGroup[0], IFrameDMContext.class);
+
+ // create two user groups containing the same registers (new register instances based on root)
+ String groupNameOne = proposeGroupName();
+ addGroup(groupNameOne, regInRootGroup);
+
+ String groupNameTwo = proposeGroupName();
+ addGroup(groupNameTwo, regInRootGroup);
+
+ // Retrieve the existing groups, expected and validated to root + 2
+ IRegisterGroupDMContext[] groups = getRegisterGroups(3);
+
+ // Read registers from group one
+ // index 0 -> root group; index1 -> group one, index2 -> group Two
+ CompositeDMContext compositeDmc = new CompositeDMContext(new IDMContext[] { frameDmc, groups[1] });
+ IRegisterDMContext[] groupOneRegisters = getRegisters(compositeDmc);
+
+ // write a register value from register group one, register index 0
+ Long iWrittenVal = Long.valueOf(oirigVal) + Long.valueOf(5);
+ String writtenValue = iWrittenVal.toString();
+ List<IRegistersChangedDMEvent> eventNotifications = writeRegisterWaitNotication(groupOneRegisters[0],
+ writtenValue, IFormattedValues.NATURAL_FORMAT);
+
+ // Validate IRegistersChangedDMEvent event notifications, one notification per group to trigger UI refresh
+ assertNotNull("No IRegistersChangedDMEvent were generated from the register value update", eventNotifications);
+ assertEquals("Incorrect number of IRegistersChangedDMEvent notifications, expecting one per group", 3,
+ eventNotifications.size());
+
+ // read the register value from user group two
+ compositeDmc = new CompositeDMContext(new IDMContext[] { frameDmc, groups[2] });
+ IRegisterDMContext[] groupTwoRegisters = getRegisters(compositeDmc);
+ String readVal = getModelDataForRegisterDataValue(groupTwoRegisters[0], IFormattedValues.NATURAL_FORMAT);
+
+ // assert the value from group two has been updated
+ assertEquals(
+ "Register[0] Value read from group two does not correspond to updated value written from group one",
+ writtenValue, readVal);
+
+ // read the register value from the root register group
+ readVal = getModelDataForRegisterDataValue(regInRootGroup[0], IFormattedValues.NATURAL_FORMAT);
+
+ // assert the value from root group has also been updated
+ assertEquals(
+ "Register[0] Value read from root group does not correspond to updated value written from group one",
+ writtenValue, readVal);
+
+ }
+
+ /**
+ * Get an array with all available register groups
+ */
+ private IRegisterGroupDMContext[] getRegisterGroups() throws Throwable {
+
+ Query<IRegisterGroupDMContext[]> queryGroupsCtx = new Query<IRegisterGroupDMContext[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterGroupDMContext[]> rm) {
+ fRegService.getRegisterGroups(fCompositeDmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().execute(queryGroupsCtx);
+
+ IRegisterGroupDMContext[] regGroupsDMCs = queryGroupsCtx.get(500, TimeUnit.MILLISECONDS);
+
+ return (regGroupsDMCs);
+ }
+
+ /**
+ * Request the existing groups and validate an expected count
+ */
+ private IRegisterGroupDMContext[] getRegisterGroups(int expectedCount) throws Throwable {
+ IRegisterGroupDMContext[] regGroupsDMCs = getRegisterGroups();
+ assertTrue("Number of groups present (" + regGroupsDMCs.length + ")" + ", and expected (" + expectedCount + ")", //$NON-NLS-1$
+ regGroupsDMCs.length == expectedCount);
+
+ return (regGroupsDMCs);
+ }
+
+ private String proposeGroupName() throws Throwable {
+ return PROPOSE_GROUP_NAME_BASE + ++fGroupNameSuffix;
+ }
+
+ private boolean canAddRegisterGroup(final IDMContext context) throws Throwable {
+ Query<Boolean> queryAction = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ fRegService.canAddRegisterGroup(context, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ return queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private boolean canEditRegisterGroup(final IRegisterGroupDMContext context) throws Throwable {
+ Query<Boolean> queryAction = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ fRegService.canEditRegisterGroup(context, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ return queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private boolean canRemoveRegisterGroups(final IRegisterGroupDMContext[] groupsContext) throws Throwable {
+ Query<Boolean> queryAction = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ fRegService.canRemoveRegisterGroups(groupsContext, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ return queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void addGroup(final String groupName, final IRegisterDMContext[] regIndexes) throws Throwable {
+
+ if (regIndexes == null || regIndexes.length < 1) {
+ fail("Invalid argument regIndexes");
+ return;
+ }
+
+ Query<Object> queryAction = new Query<Object>() {
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ IContainerDMContext contDmc = DMContexts.getAncestorOfType(regIndexes[0], IContainerDMContext.class);
+ fRegService.addRegisterGroup(contDmc, groupName, regIndexes, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void editGroup(final IRegisterGroupDMContext group, final String newGroupName, final IRegisterDMContext[] regIndexes) throws Throwable {
+
+ Query<Object> queryAction = new Query<Object>() {
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ fRegService.editRegisterGroup(group, newGroupName, regIndexes, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void removeGroups(final IRegisterGroupDMContext[] groups) throws Throwable {
+
+ Query<Object> queryAction = new Query<Object>() {
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ fRegService.removeRegisterGroups(groups, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(queryAction);
+ queryAction.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private boolean canRestoreDefaultGroups() throws Throwable {
+ Query<Boolean> queryCanRestore = new Query<Boolean>() {
+
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ //selection context not used for the time being
+ fRegService.canRestoreDefaultGroups(null, rm);
+ }
+
+ };
+
+ fRegService.getExecutor().submit(queryCanRestore);
+
+ //Validate, we can always restore to defaults
+ return queryCanRestore.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void restoreDefaultGroups() throws Throwable {
+ Query<Object> queryRestore = new Query<Object>() {
+
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ //selection context not used for the time being
+ fRegService.restoreDefaultGroups(null, rm);
+ }
+
+ };
+
+ fRegService.getExecutor().submit(queryRestore);
+
+ queryRestore.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void resetRegService() throws Throwable {
+ assert(fRegService instanceof GDBRegisters);
+ final GDBRegisters regManager = (GDBRegisters) fRegService;
+ Query<Object> queryReset = new Query<Object>() {
+
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ regManager.reset(rm);
+ }
+
+ };
+
+ regManager.getExecutor().submit(queryReset);
+
+ queryReset.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private void saveRegGroups() throws Throwable {
+ assert(fRegService instanceof GDBRegisters);
+ final GDBRegisters regManager = (GDBRegisters) fRegService;
+ Query<Object> querySave = new Query<Object>() {
+
+ @Override
+ protected void execute(DataRequestMonitor<Object> rm) {
+ regManager.save();
+ rm.done();
+ }
+
+ };
+
+ regManager.getExecutor().submit(querySave);
+
+ querySave.get(500, TimeUnit.MILLISECONDS);
+ }
+
+ private IRegisterDMData getRegisterData(final IRegisterDMContext registerDmc) throws Throwable {
+ Query<IRegisterDMData> registerDataQ = new Query<IRegisterDMData>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterDMData> rm) {
+ fRegService.getRegisterData(registerDmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(registerDataQ);
+ IRegisterDMData registerData = registerDataQ.get(500, TimeUnit.MILLISECONDS);
+ assertNotNull(registerData);
+
+ return registerData;
+ }
+
+ private FormattedValueDMData getRegisterValue(final IRegisterDMContext registerDmc) throws Throwable {
+ Query<FormattedValueDMData> registerValueQ = new Query<FormattedValueDMData>() {
+ @Override
+ protected void execute(DataRequestMonitor<FormattedValueDMData> rm) {
+ FormattedValueDMContext valueDmc = new FormattedValueDMContext(fRegService, registerDmc, IFormattedValues.NATURAL_FORMAT);
+ fRegService.getFormattedExpressionValue(valueDmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(registerValueQ);
+ FormattedValueDMData registerValue = registerValueQ.get(500, TimeUnit.MILLISECONDS);
+ assertNotNull(registerValue);
+
+ return registerValue;
+ }
+
+ private IRegisterGroupDMData getRegisterGroupData(final IRegisterGroupDMContext groupDmc) throws Throwable {
+ Query<IRegisterGroupDMData> groupDataQ = new Query<IRegisterGroupDMData>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterGroupDMData> rm) {
+ fRegService.getRegisterGroupData(groupDmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(groupDataQ);
+ IRegisterGroupDMData groupData = groupDataQ.get(500, TimeUnit.MILLISECONDS);
+ assertNotNull(groupData);
+
+ return groupData;
+ }
+
+ private IRegisterGroupDMData[] getRegisterGroupsData(final IDMContext dmc) throws Throwable {
+ Query<IRegisterGroupDMData[]> groupDataQ = new Query<IRegisterGroupDMData[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IRegisterGroupDMData[]> rm) {
+ getRegisterGroupsData(dmc, rm);
+ }
+ };
+
+ fRegService.getExecutor().submit(groupDataQ);
+ IRegisterGroupDMData[] groupsData = groupDataQ.get(500, TimeUnit.MILLISECONDS);
+ assertNotNull(groupsData);
+
+ return groupsData;
+ }
+
+ private void getRegisterGroupsData(final IDMContext dmc, final DataRequestMonitor<IRegisterGroupDMData[]> rm) {
+ assert (dmc != null);
+ final DsfExecutor executor = fRegService.getExecutor();
+ // First get all register group contexts, any register context can be used to resolve the container context
+ fRegService.getRegisterGroups(dmc, new DataRequestMonitor<IRegisterGroupDMContext[]>(executor, rm) {
+ @Override
+ protected void handleSuccess() {
+ final IRegisterGroupDMContext[] groupsCtx = getData();
+ assert (groupsCtx != null);
+
+ final IRegisterGroupDMData[] groupsData = new IRegisterGroupDMData[groupsCtx.length];
+
+ final CountingRequestMonitor crm = new CountingRequestMonitor(executor, rm) {
+ @Override
+ protected void handleCompleted() {
+ rm.setData(groupsData);
+ rm.done();
+ }
+ };
+
+ // Resolve all register group data
+ for (int i = 0; i < groupsCtx.length; i++) {
+ final int index = i;
+ fRegService.getRegisterGroupData(groupsCtx[index], new DataRequestMonitor<IRegisterGroupDMData>(executor, crm) {
+ @Override
+ protected void handleSuccess() {
+ groupsData[index] = getData();
+ crm.done();
+ }
+ });
+ }
+
+ crm.setDoneCount(groupsCtx.length);
+ }
+ });
+ }
+
+ private IRegisterDMContext[] getRegisters(int from, int to) throws Throwable {
+ MIStoppedEvent stoppedEvent = getInitialStoppedEvent();
+ IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ final IRegisterDMContext[] regDMCs = getAllRegisters(frameDmc);
+
+ // Shall not ask for more than is available
+ assertTrue(regDMCs.length > to);
+
+ // Retrieve the register range
+ final IRegisterDMContext[] regRange = Arrays.copyOfRange(regDMCs, from, to);
+
+ return regRange;
+ }
+
+ private IRegisterGroupDMContext addDefaultUserGroup() throws Throwable {
+ // Define a subset of registers to create a register group
+ final IRegisterDMContext[] regInGroup = getRegisters(0, 4);
+ // Request the addition of the new group
+ addGroup(GROUP_X, regInGroup);
+
+ // Retrieve the existing groups, expected and validated to 2
+ IRegisterGroupDMContext[] groups = getRegisterGroups(2);
+
+ // The groups are returned in reversed order to present latest created
+ // first i.e. index 0
+ // Our new group shall be at the top then i.e. 0
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regInGroup[0], IFrameDMContext.class);
+ CompositeDMContext compositeDmc = new CompositeDMContext(new IDMContext[]{groups[0], frameDmc});
+ IRegisterDMContext[] readRegisters = getRegisters(compositeDmc);
+
+ // Same objects and same order expected, although different parents
+ assertTrue(sameData(regInGroup, readRegisters, false));
+ return groups[0];
+ }
+
+ private IRegisterGroupDMContext[] addRegisterGroups(int numberOfNewGroups) throws Throwable {
+ // Define a subset of registers to associate to the new register groups
+ final IRegisterDMContext[] regInGroup = getRegisters(0, 4);
+ for (int i = 0; i < numberOfNewGroups; i++) {
+ String groupName = proposeGroupName();
+ addGroup(groupName, regInGroup);
+ }
+
+ // Expected number of groups = Root + numberofNewGroups
+ return getRegisterGroups(1 + numberOfNewGroups);
+ }
+
+ /**
+ * Check the register Data entry names are in the same order
+ */
+ private boolean sameRegisterNames(IRegisterDMData[] regNames1, IRegisterDMData[] regNames2) {
+ boolean same = false;
+ if (regNames1.length == regNames2.length) {
+ for (int i = 0; i < regNames1.length; i++) {
+ if (regNames1[i].getName().equals(regNames2[i].getName())) {
+ continue;
+ } else {
+ // Found a different name, Not the same !!
+ return false;
+ }
+ }
+
+ // All names matched !!
+ return true;
+ }
+
+ return same;
+ }
+
+ private boolean sameData(IRegisterDMContext[] regArrOne, IRegisterDMContext[] regArrTwo, boolean sameParentGroup) throws Throwable {
+ if (regArrOne.length != regArrTwo.length) {
+ return false;
+ }
+
+ for (int i=0; i< regArrOne.length; i++) {
+ if (sameParentGroup) {
+ //same group parent expected
+ final IRegisterGroupDMContext parentGroupOne = DMContexts.getAncestorOfType(regArrOne[i], IRegisterGroupDMContext.class);
+ final IRegisterGroupDMContext parentGroupTwo = DMContexts.getAncestorOfType(regArrTwo[i], IRegisterGroupDMContext.class);
+ if(!parentGroupOne.equals(parentGroupTwo)) {
+ return false;
+ }
+ }
+
+ //same data
+ IRegisterDMData dataOne = getRegisterData(regArrOne[i]);
+ IRegisterDMData dataTwo = getRegisterData(regArrTwo[i]);
+
+ if (!dataOne.getName().equals(dataTwo.getName())) {
+ return false;
+ }
+
+ //same value
+ FormattedValueDMData valueOne = getRegisterValue(regArrOne[i]);
+ FormattedValueDMData valueTwo = getRegisterValue(regArrTwo[i]);
+ if (!valueOne.getFormattedValue().equals(valueTwo.getFormattedValue())) {
+ return false;
+ }
+ }
+
+ //All data is the same
+ return true;
+ }
+
+ /**
+ * Resolve from proposed name to group sequence number e.g Group_5 -> 5
+ */
+ private int resolveGroupNameSequence(String groupName) {
+ int sequence = 0;
+ String[] strSequence = groupName.split("_");
+ assertTrue(strSequence.length == 2);
+ sequence = Integer.parseInt(strSequence[1]);
+ return sequence;
+ }
+
}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/plugin.xml b/dsf/org.eclipse.cdt.dsf.ui/plugin.xml
index e8b4e79abf..ff1d493357 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/plugin.xml
+++ b/dsf/org.eclipse.cdt.dsf.ui/plugin.xml
@@ -340,7 +340,71 @@
</count>
</with>
</activeWhen>
- </handler>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.dsf.debug.internal.ui.actions.DsfAddRegisterGroupCommand"
+ commandId="org.eclipse.cdt.debug.ui.command.addRegisterGroup">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <or>
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMNode$RegisterVMC">
+ </instanceof>
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode$RegisterGroupVMC">
+ </instanceof>
+ </or>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.dsf.debug.internal.ui.actions.DsfEditRegisterGroupCommand"
+ commandId="org.eclipse.cdt.debug.ui.command.editRegisterGroup">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode$RegisterGroupVMC">
+ </instanceof>
+ </iterate>
+ <count value="1">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.dsf.debug.internal.ui.actions.DsfRemoveRegisterGroupsCommand"
+ commandId="org.eclipse.cdt.debug.ui.command.removeRegisterGroups">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode$RegisterGroupVMC">
+ </instanceof>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
+ <handler
+ class="org.eclipse.cdt.dsf.debug.internal.ui.actions.DsfRestoreRegisterGroupsCommand"
+ commandId="org.eclipse.cdt.debug.ui.command.restoreRegisterGroups">
+ <activeWhen>
+ <with variable="selection">
+ <iterate operator="and">
+ <or>
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMNode$RegisterVMC">
+ </instanceof>
+ <instanceof value="org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode$RegisterGroupVMC">
+ </instanceof>
+ </or>
+ </iterate>
+ <count value="+">
+ </count>
+ </with>
+ </activeWhen>
+ </handler>
</extension>
<extension point="org.eclipse.core.expressions.definitions">
<definition id="org.eclipse.cdt.dsf.debug.ui.testIsUpdateModesActionSetActive">
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java
index 0761ffcf44..794833b2f6 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2013 Wind River Systems, Inc. and others.
+ * Copyright (c) 2009, 2014 Wind River Systems, Inc. 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 @@
* Wind River Systems - initial API and implementation
* Patrick Chuong (Texas Instruments) - Bug 315446: Invalid event breakpoint type (group) name
* Alvaro Sanchez-Leon (Ericsson AB) - Support for Step into selection (bug 244865)
+ * Alvaro Sanchez-Leon (Ericsson AB) - Support Register Groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui;
@@ -18,6 +19,14 @@ public class Messages extends NLS {
public static String ToggleBreakpointsTargetFactory_description;
public static String ToggleBreakpointsTargetFactory_name;
public static String DsfUIStepIntoEditorSelection;
+ public static String RegisterGroupInfo;
+ public static String Information;
+ public static String DefaultRegistersGroupName;
+ public static String ProposeGroupNameRoot;
+ public static String RegisterGroupConfirmRestoreTitle;
+ public static String RegisterGroupConfirmRestoreMessage;
+ public static String RegisterGroupRestore;
+ public static String RegisterGroupRestoreCancel;
static {
// initialize resource bundle
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties
index 37451dbd58..7c11584161 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/Messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2009, 2013 Wind River Systems and others.
+# Copyright (c) 2009, 2014 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
@@ -9,9 +9,19 @@
# Wind River Systems - initial API and implementation
# Ericsson - added Tracepoint support
# Ericsson - added Step into selection support
+# Ericsson - Support Register Groups
###############################################################################
ToggleBreakpointsTargetFactory_description=Standard C/C++ breakpoint type.
ToggleBreakpointsTargetFactory_name=C/C++ Breakpoints
DsfUIStepIntoEditorSelection=Step Into
+Information=Information
+RegisterGroupInfo=Register Group
+DefaultRegistersGroupName=New Group
+ProposeGroupNameRoot=Group_
+RegisterGroupConfirmRestoreTitle=Register Groups - Confirm Restore
+RegisterGroupConfirmRestoreMessage=Are you sure you want to restore to the default register group(s) ?
+RegisterGroupRestore=OK
+RegisterGroupRestoreCancel=Cancel
+
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/AbstractDsfRegisterGroupActions.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/AbstractDsfRegisterGroupActions.java
new file mode 100644
index 0000000000..9514e57ad2
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/AbstractDsfRegisterGroupActions.java
@@ -0,0 +1,1010 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson AB 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:
+ * Alvaro Sanchez-Leon (Ericsson) - First Implementation and API (Bug 235747)
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui.actions;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
+import org.eclipse.cdt.debug.internal.core.model.IRegisterGroupDescriptor;
+import org.eclipse.cdt.debug.internal.ui.actions.RegisterGroupDialog;
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.internal.ui.Messages;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
+import org.eclipse.cdt.dsf.debug.service.IRegisters2;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPart;
+
+public abstract class AbstractDsfRegisterGroupActions extends AbstractHandler {
+ private static final String BLANK_STRING = ""; //$NON-NLS-1$
+ private static final String REG_GROUP_ACTION_FAILED = "Register Group Action failed\n"; //$NON-NLS-1$
+
+ private class RegisterGroupDialogRunnable implements Runnable {
+ private String fGroupName = BLANK_STRING;
+ private IRegisterDescriptor[] fSelectedRegisters = null;
+ private final IRegisterDescriptor[] fallRegisters;
+ private final Shell fShell;
+ private final DataRequestMonitor<IRegisterGroupDescriptor> fMonitor;
+
+ private RegisterGroupDialogRunnable(Shell shell, String groupName, IRegisterDescriptor[] allRegisters,
+ IRegisterDescriptor[] selectedRegisters, DataRequestMonitor<IRegisterGroupDescriptor> rm) {
+ fallRegisters = allRegisters;
+ fSelectedRegisters = selectedRegisters;
+ fShell = shell;
+ fGroupName = groupName;
+ fMonitor = rm;
+ }
+
+ @Override
+ public void run() {
+ RegisterGroupDialog dialog = new RegisterGroupDialog(fShell, fGroupName, fallRegisters, fSelectedRegisters);
+ if (dialog.open() == Window.OK) {
+ String groupName = dialog.getName();
+ IRegisterDescriptor[] iSelectedRegisters = dialog.getDescriptors();
+ IRegisterGroupDescriptor groupDescriptor = createGroupDescriptor(groupName, iSelectedRegisters);
+
+ fMonitor.setData(groupDescriptor);
+ } else {
+ fMonitor.cancel();
+ return;
+ }
+
+ fMonitor.done();
+ }
+ }
+
+ private class RegisterDescriptor implements IRegisterDescriptor {
+ private final IRegisterDMContext fRegContext;
+ private String fOriginalGroupName = BLANK_STRING;
+ private String fName = BLANK_STRING;
+
+ private RegisterDescriptor(String groupName, IRegisterDMContext regContext, String name) {
+ fRegContext = regContext;
+ fName = name;
+ // initial group Name
+ fOriginalGroupName = groupName;
+ }
+
+ @Override
+ public String getName() {
+ return fName;
+ }
+
+ @Override
+ public String getGroupName() {
+ return fOriginalGroupName;
+ }
+ }
+
+ private class SelectionDMContext {
+ private final IDMContext fcontext;
+ private final DsfSession fsession;
+
+ private SelectionDMContext(IStructuredSelection selection) throws DebugException {
+ if (!(selection.getFirstElement() instanceof IDMVMContext)) {
+ abort("Unrecognized element from the provided register selection"); //$NON-NLS-1$
+ }
+
+ // Resolve the context
+ IDMVMContext context = (IDMVMContext) selection.getFirstElement();
+ fcontext = context.getDMContext();
+
+ // Resolve the session
+ String sessionId = fcontext.getSessionId();
+ fsession = DsfSession.getSession(sessionId);
+
+ if (fsession == null || !(fsession.isActive())) {
+ abort("Sesssion inactive"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * This method has to be called under the executor's thread
+ */
+ public IRegisters2 resolveService() throws DebugException {
+ // Resolve the registers service
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), fsession.getId());
+ IRegisters service = tracker.getService(IRegisters.class, null);
+
+ tracker.dispose();
+
+ if (!(service instanceof IRegisters2)) {
+ abort("Unable to resolve IRegisters2 service"); //$NON-NLS-1$
+ }
+
+ return (IRegisters2) service;
+ }
+
+ private void abort(String message) throws DebugException {
+ // Interrupt on error
+ IStatus status = new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IStatus.ERROR, message, null);
+ throw new DebugException(status);
+ }
+
+ }
+
+ private interface DialogRegisterProvider {
+ public IRegisterDescriptor[] getAllRegisters();
+
+ public IRegisterDescriptor[] getcheckedRegisters();
+ }
+
+ protected void addRegisterGroup(final IWorkbenchPart part, final IStructuredSelection selection) {
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+ selectionContext.fsession.getExecutor().execute(new DsfRunnable() {
+
+ @Override
+ public void run() {
+ final IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (CoreException e) {
+ failed(e);
+ return;
+ }
+
+ // continue to process
+ processAddRegisterGroup(part.getSite().getShell(), selectionContext,
+ resolveSelectedRegisters(selection), registersService);
+ }});
+
+ } catch (DebugException e) {
+ }
+ }
+
+ protected boolean canAddRegisterGroup(IWorkbenchPart part, IStructuredSelection selection) {
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+ Query<Boolean> query = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (DebugException e) {
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+
+ if (registersService != null) {
+ registersService.canAddRegisterGroup(selectionContext.fcontext, rm);
+ } else {
+ rm.setData(false);
+ rm.done();
+ }
+ }
+ };
+ selectionContext.fsession.getExecutor().execute(query);
+ return query.get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ } catch (DebugException e1) {
+ }
+
+ return false;
+ }
+
+ protected void editRegisterGroup(final IWorkbenchPart part, IStructuredSelection selection) {
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+
+ selectionContext.fsession.getExecutor().execute(new DsfRunnable() {
+ @Override
+ public void run() {
+ // Create a services tracker
+ final IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (CoreException e) {
+ failed(e);
+ return;
+ }
+
+ processEditRegisterGroup(part.getSite().getShell(), selectionContext,
+ registersService);
+ }
+
+ });
+ } catch (DebugException e) {
+ }
+ }
+
+ protected boolean canEditRegisterGroup(IWorkbenchPart part, IStructuredSelection selection) {
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+ final IDMContext context = selectionContext.fcontext;
+
+ // The group to be edited needs to be selected
+ if (!(context instanceof IRegisterGroupDMContext)) {
+ return false;
+ }
+
+ Query<Boolean> query = new Query<Boolean>() {
+ @Override
+ protected void execute(final DataRequestMonitor<Boolean> rm) {
+ IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (DebugException e) {
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+
+ if (registersService != null) {
+ registersService.canEditRegisterGroup((IRegisterGroupDMContext) context, rm);
+ } else {
+ rm.setData(false);
+ rm.done();
+ }
+ }
+ };
+ selectionContext.fsession.getExecutor().execute(query);
+ return query.get();
+
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ } catch (DebugException e1) {
+ }
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#removeRegisterGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ protected void removeRegisterGroups(IWorkbenchPart part, IStructuredSelection selection) {
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+
+ final IRegisterGroupDMContext[] groups = resolveSelectedGroups(selection);
+ selectionContext.fsession.getExecutor().execute(new DsfRunnable() {
+ @Override
+ public void run() {
+ IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (CoreException e) {
+ failed(e);
+ return;
+ }
+
+ registersService.removeRegisterGroups(groups, new RequestMonitor(registersService.getExecutor(), null) {
+ });
+ }
+ });
+ } catch (DebugException e) {
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canRemoveRegisterGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ protected boolean canRemoveRegisterGroups(IWorkbenchPart part, IStructuredSelection selection) {
+ final SelectionDMContext selectionContext;
+ try {
+ selectionContext = new SelectionDMContext(selection);
+ } catch (DebugException e) {
+ // No DM context present or group registers service found in the selection
+ return false;
+ }
+
+ //resolve the selected groups
+ final IRegisterGroupDMContext[] groups = resolveSelectedGroups(selection);
+ if (groups == null || groups.length < 1){
+ return false;
+ }
+
+ //Prepare to Query the service and check if the selected groups can be removed
+ Query<Boolean> query = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ IRegisters2 regService;
+ try {
+ regService = selectionContext.resolveService();
+ } catch (DebugException e) {
+ // Unable to resolve the registers service
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+
+ regService.canRemoveRegisterGroups(groups, rm);
+ }
+ };
+
+ //Execute the query
+ selectionContext.fsession.getExecutor().execute(query);
+
+ try {
+ // return the answer from the service
+ return query.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+
+ // No positive answer from the service
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#restoreDefaultGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ protected void restoreDefaultGroups(IWorkbenchPart part, IStructuredSelection selection) {
+ if (!restoreConfirmed()) {
+ return;
+ }
+
+ try {
+ final SelectionDMContext selectionContext = new SelectionDMContext(selection);
+
+ selectionContext.fsession.getExecutor().execute(new DsfRunnable() {
+ @Override
+ public void run() {
+ IRegisters2 registersService;
+ try {
+ registersService = selectionContext.resolveService();
+ } catch (CoreException e) {
+ failed(e);
+ return;
+ }
+
+ // no success handler needed
+ registersService.restoreDefaultGroups(null, new RequestMonitor(registersService.getExecutor(), null));
+ }
+ });
+ } catch (DebugException e) {
+ failed(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.actions.IRegisterGroupActionsTarget#canRestoreDefaultGroups(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ protected boolean canRestoreDefaultGroups(IWorkbenchPart part, IStructuredSelection selection) {
+ final SelectionDMContext selectionContext;
+ try {
+ selectionContext = new SelectionDMContext(selection);
+ } catch (DebugException e) {
+ // No DM context present or group registers service found in the selection
+ return false;
+ }
+
+ //Prepare to Query the service
+ Query<Boolean> query = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ IRegisters2 regService;
+ try {
+ regService = selectionContext.resolveService();
+ } catch (DebugException e) {
+ // Unable to resolve the registers service
+ rm.setData(false);
+ rm.done();
+ return;
+ }
+
+ regService.canRestoreDefaultGroups(selectionContext.fcontext, rm);
+ }
+ };
+
+ //Execute the query
+ selectionContext.fsession.getExecutor().execute(query);
+
+ try {
+ // return the answer from the service
+ return query.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+
+ // No positive answer from the service
+ return false;
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private void processAddRegisterGroup(final Shell shell, final SelectionDMContext selectionContext, final IRegisterDMContext[] selectedRegisters,
+ final IRegisters2 regServiceManager) {
+
+ final DsfSession session = selectionContext.fsession;
+ final DsfExecutor executor = session.getExecutor();
+
+ final IContainerDMContext contDmc = DMContexts.getAncestorOfType(selectionContext.fcontext, IContainerDMContext.class);
+ // Using the container context to get all existing registers from the target instead of a limited set of registers for a selected group
+ regServiceManager.getRegisters(contDmc, new DataRequestMonitor<IRegisterDMContext[]>(
+ executor, null) {
+
+ @Override
+ protected void handleSuccess() {
+ // Get Register Contexts
+ final IRegisterDMContext[] rootRegisters = getData();
+
+ if (rootRegisters.length < 1) {
+ //The target is expected to have registers, an error has happened !
+ assert false;
+ noRegisterGroupFoundErr("Add Register Group", this); //$NON-NLS-1$
+ return;
+ }
+
+ //Find the root register group, containing all the registers associated to a target, from any of the root registers
+ final IRegisterGroupDMContext rootGroupDmc = DMContexts.getAncestorOfType(rootRegisters[0], IRegisterGroupDMContext.class);
+
+ // Get data for all available registers
+ getRegistersData(rootRegisters, regServiceManager, new DataRequestMonitor<IRegisterDMData[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ final IRegisterDMData[] rootRegistersData = getData();
+
+ getRegistersData(selectedRegisters, regServiceManager, new DataRequestMonitor<IRegisterDMData[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ // Get data for all selected registers i.e. selected for the new group
+ final IRegisterDMData[] selectedRegistersData = getData();
+
+ //Need the root group name to build register descriptors
+ regServiceManager.getRegisterGroupData(rootGroupDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ final IRegisterGroupDMData rootGroupData = getData();
+ // request for the next unused group name to propose it to the user
+ proposeGroupName(rootRegisters, regServiceManager, new DataRequestMonitor<String>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ String proposedGroupName = getData();
+
+ String rootGroupName = (rootGroupData == null) ? BLANK_STRING
+ : rootGroupData.getName();
+ // Create the Register descriptors
+ DialogRegisterProvider descriptors = buildDescriptors(
+ rootGroupName, rootRegisters,
+ rootRegistersData,
+ selectedRegistersData);
+ // Create Dialog Resolve selection to DSF
+ // Registers
+ getDialogSelection(
+ shell,
+ proposedGroupName,
+ descriptors.getAllRegisters(),
+ descriptors.getcheckedRegisters(),
+ new DataRequestMonitor<IRegisterGroupDescriptor>(
+ executor, null) {
+ @Override
+ protected void handleSuccess() {
+ try {
+ addRegisterGroup(
+ regServiceManager,
+ getData(), contDmc);
+ } catch (CoreException e) {
+ failed(e);
+ }
+ };
+ });
+ }
+ });
+
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ });
+ }
+
+ private void noRegisterGroupFoundErr(String msgOrigin, RequestMonitor rm) {
+ String message = msgOrigin + ": Unable to resolve root Group"; //$NON-NLS-1$
+ IStatus status = new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED,
+ REG_GROUP_ACTION_FAILED + message, new Exception(message));
+ DsfUIPlugin.log(status);
+ rm.setStatus(status);
+ rm.done();
+ }
+
+ private void proposeGroupName(IRegisterDMContext[] registers, final IRegisters2 regServiceManager, final DataRequestMonitor<String> rm) {
+ assert(registers != null && registers.length > 0);
+
+ final DsfExecutor executor = regServiceManager.getExecutor();
+ if (registers != null && registers.length > 0) {
+ //First get all register group contexts, any register context can be used to resolve the container context
+ regServiceManager.getRegisterGroups(registers[0], new DataRequestMonitor<IRegisterGroupDMContext[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ IRegisterGroupDMContext[] groupsCtx = getData();
+ assert (groupsCtx != null);
+
+ final IRegisterGroupDMData[] groupsData = new IRegisterGroupDMData[groupsCtx.length];
+
+ final CountingRequestMonitor crm = new CountingRequestMonitor(executor, rm) {
+ @Override
+ protected void handleCompleted() {
+ //GroupsData is resolved now
+ //Select an unused name
+ String unusedGroupName = Messages.ProposeGroupNameRoot + (resolveGroupNameWaterMark(groupsData) + 1);
+ rm.setData(unusedGroupName);
+ rm.done();
+ }
+ };
+
+ //Resolve all register group data
+ for (int i=0; i < groupsCtx.length; i++) {
+ final int index = i;
+ regServiceManager.getRegisterGroupData(groupsCtx[index], new DataRequestMonitor<IRegisterGroupDMData>(executor, crm){
+ @Override
+ protected void handleSuccess() {
+ groupsData[index] = getData();
+ crm.done();
+ }
+ });
+ }
+
+ crm.setDoneCount(groupsCtx.length);
+ }
+ });
+ } else {
+ //Should not happen
+ rm.setData(Messages.DefaultRegistersGroupName);
+ rm.done();
+ }
+ }
+
+ // Adjust water mark suffix used to suggest register group names
+ private Integer resolveGroupNameWaterMark(IRegisterGroupDMData[] groupsData) {
+ // check only for this name pattern
+ Pattern pattern = Pattern.compile("^group_(\\d*)$"); //$NON-NLS-1$
+ Matcher matcher = pattern.matcher(""); //$NON-NLS-1$
+ int water_mark = 0;
+ for (IRegisterGroupDMData groupData : groupsData) {
+ // Normalize the name to lower case comparison
+ String name = groupData.getName().trim().toLowerCase();
+ // tracking proposed group names e.d. Group_1, Group_2, etc..,
+ // otherwise no need to update the water mark
+ if (matcher.reset(name).matches()) {
+ // Obtain the numerical suffix
+ String number = matcher.replaceAll("$1"); //$NON-NLS-1$
+ try {
+ int nameSequence = Integer.valueOf(number).intValue();
+ if (nameSequence > water_mark) {
+ // The new value is bigger so lets move up the water mark
+ water_mark = nameSequence;
+ }
+ } catch (NumberFormatException e) {
+ // Quite unlikely and only causing a possibility to
+ // propose a group name that already exists.
+ }
+ }
+ }
+
+ return Integer.valueOf(water_mark);
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private void processEditRegisterGroup(final Shell shell, final SelectionDMContext selectionContext, final IRegisters2 regServiceManager) {
+
+ final DsfSession session = selectionContext.fsession;
+ final DsfExecutor executor = session.getExecutor();
+
+ // Get a handle to the context of the group being edited
+ final IRegisterGroupDMContext groupDmc = DMContexts.getAncestorOfType(selectionContext.fcontext,
+ IRegisterGroupDMContext.class);
+
+ // Getting the children of the selected group
+ regServiceManager.getRegisters(selectionContext.fcontext,
+ new DataRequestMonitor<IRegisterDMContext[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ // Get children Register Contexts
+ final IRegisterDMContext[] childRegisters = getData();
+
+ final IContainerDMContext contDmc = DMContexts.getAncestorOfType(selectionContext.fcontext, IContainerDMContext.class);
+ // Using the container context to get all existing registers from the target instead of a limited set of registers for a selected group
+ // This is needed to populate the dialog with all available registers to pick from
+ regServiceManager.getRegisters(contDmc, new DataRequestMonitor<IRegisterDMContext[]>(
+ executor, null) {
+ @Override
+ protected void handleSuccess() {
+ final IRegisterDMContext[] rootRegisters = getData();
+
+ if (rootRegisters.length < 1) {
+ //The target is expected to have a root register group and associated registers, an error has happened !
+ assert false;
+ noRegisterGroupFoundErr("Edit Register Group", this); //$NON-NLS-1$
+ return;
+ }
+
+ // We need to resolve the names for all root registers
+ getRegistersData(rootRegisters, regServiceManager, new DataRequestMonitor<IRegisterDMData[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ final IRegisterDMData[] rootRegistersData = getData();
+
+ getRegistersData(childRegisters, regServiceManager, new DataRequestMonitor<IRegisterDMData[]>(executor, null) {
+ @Override
+ protected void handleSuccess() {
+ // Get register data for all selected registers i.e. selected for the new group
+ final IRegisterDMData[] childRegisterData = getData();
+
+ // Need to get the parent group name. Used on the register descriptors
+ final IRegisterGroupDMContext rootGroupDmc = DMContexts.getAncestorOfType(rootRegisters[0], IRegisterGroupDMContext.class);
+ regServiceManager.getRegisterGroupData(rootGroupDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(
+ executor, null) {
+ @Override
+ protected void handleSuccess() {
+ IRegisterGroupDMData rootGroupData = getData();
+ final String rootGroupName = (rootGroupData == null) ? BLANK_STRING
+ : rootGroupData.getName();
+
+ regServiceManager.getRegisterGroupData(groupDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(
+ executor, null) {
+ @Override
+ protected void handleSuccess() {
+ // Resolve the name of the selected group being edited
+ String selGroupName = getData().getName();
+ // Create the Register descriptors to
+ // access all children registers
+ DialogRegisterProvider descriptors = buildDescriptors(
+ rootGroupName, rootRegisters,
+ rootRegistersData,
+ childRegisterData);
+
+ // Create Dialog to Resolve new user
+ // selection of group name and registers
+ getDialogSelection(
+ shell,
+ selGroupName,
+ descriptors.getAllRegisters(),
+ descriptors
+ .getcheckedRegisters(),
+ new DataRequestMonitor<IRegisterGroupDescriptor>(
+ executor, null) {
+ @Override
+ protected void handleSuccess() {
+ try {
+ editRegisterGroup(
+ groupDmc,
+ regServiceManager,
+ getData());
+ } catch (CoreException e) {
+ failed(e);
+ }
+ };
+ });
+ }
+ });
+ };
+
+ });
+ }
+ });
+
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ private IRegisterGroupDMContext[] resolveSelectedGroups(IStructuredSelection selection) {
+ IRegisterGroupDMContext[] selectedGroups = null;
+ List<IRegisterGroupDMContext> groupList = new ArrayList<IRegisterGroupDMContext>();
+ if (selection != null && !selection.isEmpty()) {
+ for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ if (element instanceof IDMVMContext) {
+ IDMContext dmContext = ((IDMVMContext) element).getDMContext();
+ // Make sure this selection is a group
+ if (dmContext instanceof IRegisterGroupDMContext) {
+ IRegisterGroupDMContext groupDmc = (IRegisterGroupDMContext) dmContext;
+ groupList.add(groupDmc);
+ }
+ }
+ }
+
+ }
+
+ selectedGroups = groupList.toArray(new IRegisterGroupDMContext[groupList.size()]);
+ return selectedGroups;
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private IRegisterDMContext[] resolveSelectedRegisters(IStructuredSelection selection) {
+ List<IRegisterDMContext> selectedRegistersList = new ArrayList<IRegisterDMContext>();
+ for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ IDMVMContext regContext = null;
+ if (element instanceof IDMVMContext) {
+ regContext = (IDMVMContext) element;
+ IRegisterDMContext registerDmc = DMContexts.getAncestorOfType(regContext.getDMContext(),
+ IRegisterDMContext.class);
+ if (registerDmc != null) {
+ selectedRegistersList.add(registerDmc);
+ }
+ }
+ }
+
+ IRegisterDMContext[] selectedRegisters = selectedRegistersList
+ .toArray(new IRegisterDMContext[selectedRegistersList.size()]);
+ return selectedRegisters;
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private IRegisterDMContext[] getRegisterContexts(IRegisterDescriptor[] registerDescriptors) throws CoreException {
+ IRegisterDMContext[] regContexts = new IRegisterDMContext[registerDescriptors.length];
+ for (int i = 0; i < registerDescriptors.length; i++) {
+ if (registerDescriptors[i] instanceof RegisterDescriptor) {
+ regContexts[i] = ((RegisterDescriptor) registerDescriptors[i]).fRegContext;
+ } else {
+ // Interrupt on error
+ IStatus status = new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IStatus.ERROR,
+ "Unexpected IRegisterDescription instance type", null); //$NON-NLS-1$
+ throw new CoreException(status);
+ }
+ }
+
+ return regContexts;
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private void getDialogSelection(Shell shell, String originalGroupName,
+ IRegisterDescriptor[] allRegisters, IRegisterDescriptor[] checkedRegisters,
+ DataRequestMonitor<IRegisterGroupDescriptor> rm) {
+ RegisterGroupDialogRunnable dialog = new RegisterGroupDialogRunnable(shell, originalGroupName, allRegisters,
+ checkedRegisters, rm);
+ shell.getDisplay().asyncExec(dialog);
+ }
+
+ private IRegisterGroupDescriptor createGroupDescriptor(final String groupName,
+ final IRegisterDescriptor[] iSelectedRegisters) {
+ IRegisterGroupDescriptor groupDescriptor = new IRegisterGroupDescriptor() {
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return groupName;
+ }
+
+ @Override
+ public IRegisterDescriptor[] getChildren() throws CoreException {
+ return iSelectedRegisters;
+ }
+ };
+
+ return groupDescriptor;
+ }
+
+ /**
+ * Build descriptor adapters to dialog interface both all registers as well as registers to be pre-selected on the
+ * dialog
+ *
+ * @param checkedRegistersData
+ */
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private DialogRegisterProvider buildDescriptors(String groupName, IRegisterDMContext[] registers,
+ IRegisterDMData[] registerData, IRegisterDMData[] checkedRegistersData) {
+ assert (registers.length == registerData.length);
+
+ List<RegisterDescriptor> checkedDescriptorsList = new ArrayList<RegisterDescriptor>();
+
+ final RegisterDescriptor[] regDescriptors = new RegisterDescriptor[registers.length];
+
+ Map<String, RegisterDescriptor> mapNameToRegDescriptor = new HashMap<String, RegisterDescriptor>();
+
+ for (int i = 0; i < registers.length; i++) {
+ regDescriptors[i] = new RegisterDescriptor(groupName, registers[i], registerData[i].getName());
+ mapNameToRegDescriptor.put(regDescriptors[i].getName(), regDescriptors[i]);
+ }
+
+ for (int i = 0; i < checkedRegistersData.length; i++) {
+ // Resolve the descriptor by name
+ RegisterDescriptor descriptor = mapNameToRegDescriptor.get(checkedRegistersData[i].getName());
+
+ // All checked registers are expected to be part of the complete list
+ assert (descriptor != null);
+
+ // prevent duplicates or null values, duplicates are possible since the selected registers
+ // may come from different groups
+ if (descriptor != null && !checkedDescriptorsList.contains(descriptor)) {
+ checkedDescriptorsList.add(descriptor);
+ }
+ }
+
+ final RegisterDescriptor[] checkedRegDescriptors = checkedDescriptorsList
+ .toArray(new RegisterDescriptor[checkedDescriptorsList.size()]);
+
+ DialogRegisterProvider provider = new DialogRegisterProvider() {
+ @Override
+ public IRegisterDescriptor[] getcheckedRegisters() {
+ return checkedRegDescriptors;
+ }
+
+ @Override
+ public IRegisterDescriptor[] getAllRegisters() {
+ return regDescriptors;
+ }
+ };
+
+ return provider;
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private void addRegisterGroup(IRegisters2 regServiceManager,
+ IRegisterGroupDescriptor groupDescriptor, IContainerDMContext contDmc) throws CoreException {
+ IRegisterDescriptor[] selectedRegisters = groupDescriptor.getChildren();
+ if (selectedRegisters != null) {
+ String groupName = groupDescriptor.getName();
+ // Register the addition of the group and notify the change
+ IRegisterDMContext[] registers = getRegisterContexts(selectedRegisters);
+ regServiceManager.addRegisterGroup(contDmc, groupName, registers, new RequestMonitor(
+ regServiceManager.getSession().getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus() != null && getStatus().getCode() == IDsfStatusConstants.NOT_SUPPORTED) {
+ // This user request is not supported, notify the user
+ notifyUser(getStatus().getMessage());
+ }
+
+ };
+ });
+ }
+ }
+
+ @ConfinedToDsfExecutor("selectionContext.fsession.getExecutor()")
+ private void editRegisterGroup(IRegisterGroupDMContext group, IRegisters2 regServiceManager,
+ IRegisterGroupDescriptor groupDescriptor) throws CoreException {
+ IRegisterDescriptor[] selectedRegisters = groupDescriptor.getChildren();
+ if (selectedRegisters != null) {
+ String groupName = groupDescriptor.getName();
+ // Register the addition of the group and notify the change
+ regServiceManager.editRegisterGroup(group, groupName, getRegisterContexts(selectedRegisters),
+ new RequestMonitor(regServiceManager.getSession().getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus() != null && getStatus().getCode() == IDsfStatusConstants.NOT_SUPPORTED) {
+ // This user request is not supported, notify the user
+ notifyUser(getStatus().getMessage());
+ }
+
+ };
+ });
+ }
+ }
+
+ private void failed(Throwable e) {
+ IStatus status = new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED,
+ REG_GROUP_ACTION_FAILED + e.getMessage(), e);
+ DsfUIPlugin.log(status);
+ }
+
+ private void notifyUser(final String message) {
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ Shell parent = DsfUIPlugin.getActiveWorkbenchShell();
+ if (parent != null) {
+ MessageDialog.openInformation(parent, Messages.Information, Messages.RegisterGroupInfo + ": " + message); //$NON-NLS-1$
+ }
+ }
+ };
+
+ Display.getDefault().asyncExec(runnable);
+ }
+
+ /**
+ * @return true - OK to restore
+ */
+ private boolean restoreConfirmed() {
+ ConfirmRestoreDialog restoreDialog = new ConfirmRestoreDialog();
+ Display.getDefault().syncExec(restoreDialog);
+
+ return restoreDialog.fRestore;
+ }
+
+ private class ConfirmRestoreDialog implements Runnable {
+
+ private Boolean fRestore = false;
+
+ @Override
+ public void run() {
+ Shell parent = DsfUIPlugin.getActiveWorkbenchShell();
+ if (parent != null) {
+
+ String title = Messages.RegisterGroupConfirmRestoreTitle;
+ String message = Messages.RegisterGroupConfirmRestoreMessage;
+ String[] buttonLabels = new String[]{Messages.RegisterGroupRestore, Messages.RegisterGroupRestoreCancel,
+ };
+ MessageDialog dialog = new MessageDialog(parent, title, null, message, MessageDialog.QUESTION,
+ buttonLabels, 0);
+ int res = dialog.open();
+ if (res == 0) { // RESTORE
+ fRestore = true;
+ } else if (res == 1) { // CANCEL
+ fRestore = false;
+ }
+ }
+ }
+
+ }
+
+
+ private void getRegistersData(IRegisterDMContext[] regDMCs, IRegisters2 regService, final DataRequestMonitor<IRegisterDMData[]> rm) {
+ final IRegisterDMData[] regDataArray = new IRegisterDMData[regDMCs.length];
+ final DsfExecutor executor = regService.getExecutor();
+
+ final CountingRequestMonitor crm = new CountingRequestMonitor(executor, rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(regDataArray);
+ rm.done();
+ }
+ };
+
+ for (int i = 0; i < regDMCs.length; i++) {
+ final int index = i;
+ regService.getRegisterData(regDMCs[index], new DataRequestMonitor<IRegisterDMData>(executor, crm) {
+ @Override
+ protected void handleSuccess() {
+ regDataArray[index] = getData();
+ crm.done();
+ }
+ });
+ }
+
+ crm.setDoneCount(regDMCs.length);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfAddRegisterGroupCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfAddRegisterGroupCommand.java
new file mode 100644
index 0000000000..7e89dac057
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfAddRegisterGroupCommand.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command performing adding a register group.
+ * @since 2.4
+ */
+public class DsfAddRegisterGroupCommand extends AbstractDsfRegisterGroupActions {
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ Object p = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_PART_NAME);
+ if (s instanceof IStructuredSelection && p instanceof IWorkbenchPart) {
+ state = canAddRegisterGroup((IWorkbenchPart)p, (IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ IWorkbenchPart part = HandlerUtil.getActivePart(event);
+ if (selection instanceof IStructuredSelection) {
+ addRegisterGroup(part, (IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfEditRegisterGroupCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfEditRegisterGroupCommand.java
new file mode 100644
index 0000000000..5872ea1a04
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfEditRegisterGroupCommand.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command performing adding a register group.
+ * @since 2.4
+ */
+public class DsfEditRegisterGroupCommand extends AbstractDsfRegisterGroupActions {
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ Object p = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_PART_NAME);
+ if (s instanceof IStructuredSelection && p instanceof IWorkbenchPart) {
+ state = canEditRegisterGroup((IWorkbenchPart)p, (IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ IWorkbenchPart part = HandlerUtil.getActivePart(event);
+ if (selection instanceof IStructuredSelection) {
+ editRegisterGroup(part, (IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRemoveRegisterGroupsCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRemoveRegisterGroupsCommand.java
new file mode 100644
index 0000000000..42a02b5e45
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRemoveRegisterGroupsCommand.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command performing adding a register group.
+ * @since 2.4
+ */
+public class DsfRemoveRegisterGroupsCommand extends AbstractDsfRegisterGroupActions {
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ Object p = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_PART_NAME);
+ if (s instanceof IStructuredSelection && p instanceof IWorkbenchPart) {
+ state = canRemoveRegisterGroups((IWorkbenchPart)p, (IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ IWorkbenchPart part = HandlerUtil.getActivePart(event);
+ if (selection instanceof IStructuredSelection) {
+ removeRegisterGroups(part, (IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRestoreRegisterGroupsCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRestoreRegisterGroupsCommand.java
new file mode 100644
index 0000000000..c8cc4e53be
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/actions/DsfRestoreRegisterGroupsCommand.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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 Khouzam (Ericsson) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Command performing adding a register group.
+ * @since 2.4
+ */
+public class DsfRestoreRegisterGroupsCommand extends AbstractDsfRegisterGroupActions {
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ boolean state = false;
+ if (evaluationContext instanceof IEvaluationContext) {
+ Object s = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_MENU_SELECTION_NAME);
+ Object p = ((IEvaluationContext) evaluationContext).getVariable(ISources.ACTIVE_PART_NAME);
+ if (s instanceof IStructuredSelection && p instanceof IWorkbenchPart) {
+ state = canRestoreDefaultGroups((IWorkbenchPart)p, (IStructuredSelection)s);
+ }
+ }
+ setBaseEnabled(state);
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ IWorkbenchPart part = HandlerUtil.getActivePart(event);
+ if (selection instanceof IStructuredSelection) {
+ restoreDefaultGroups(part, (IStructuredSelection)selection);
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java
index 81522fd21d..a6e95a7b36 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2010 Wind River Systems and others.
+ * Copyright (c) 2006, 2014 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Wind River Systems - initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Allow user to edit the register groups (Bug 235747)
*******************************************************************************/
package org.eclipse.cdt.dsf.internal.ui;
@@ -22,6 +23,8 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
@@ -168,5 +171,19 @@ public class DsfUIPlugin extends AbstractUIPlugin {
public static IStatus newErrorStatus(int code, String message, Throwable exception) {
return new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, code, message, exception);
}
+
+ /**
+ * Returns the active workbench shell or <code>null</code> if none
+ *
+ * @return the active workbench shell or <code>null</code> if none
+ */
+ public static Shell getActiveWorkbenchShell() {
+ IWorkbenchWindow window = getDefault().getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ return window.getShell();
+ }
+
+ return null;
+ }
}
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRegisters2.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRegisters2.java
new file mode 100644
index 0000000000..6939580d86
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRegisters2.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ * Alvaro Sanchez-Leon (Ericsson) - First API (Bug 235747)
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.service;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+
+/**
+ * Service extension of IRegisters to manage user defined Register Groups
+ * @since 2.6
+ */
+public interface IRegisters2 extends IRegisters {
+ /**
+ * Returns a boolean indicating if it is allowed to add a new register group with the given selected context
+ *
+ * @param rm - monitor encapsulating the response
+ */
+ public void canAddRegisterGroup(IDMContext ctx, DataRequestMonitor<Boolean> rm);
+
+ /**
+ * Add a Register group referencing the given registers
+ *
+ * @param ctx - A context containing a parent group context e.g. IContainerDMContext
+ * @param name - register group name
+ * @param registers - registers part of this new group
+ * @param rm - request monitor
+ */
+ public void addRegisterGroup(IDMContext ctx, String name, IRegisterDMContext[] registers, RequestMonitor rm);
+
+ /**
+ * Returns a boolean indicating if it is allowed to edit the given group
+ *
+ * @param rm - monitor encapsulating the response
+ */
+ public void canEditRegisterGroup(IRegisterGroupDMContext group,
+ DataRequestMonitor<Boolean> rm);
+
+ /**
+ * Edit the given register group and update its name and associated registers
+ *
+ * @param group - group to be edited
+ * @param groupName - new group name or null if name is not to be changed
+ * @param registers - new list of registers for this group or null if the list of registers is not be changed
+ * @param rm - request monitor
+ */
+ public void editRegisterGroup(IRegisterGroupDMContext group, String groupName,
+ IRegisterDMContext[] registers, RequestMonitor rm);
+
+ /**
+ * Returns a boolean indicating if it is allowed to remove the given registers groups
+ * @param groups - list of register group contexts to be removed
+ * @param rm
+ */
+ public void canRemoveRegisterGroups(IRegisterGroupDMContext[] groups,
+ DataRequestMonitor<Boolean> rm);
+
+ /**
+ * Remove the given register groups
+ *
+ * @param groups - groups that shall be removed
+ * @param rm - request monitor
+ */
+ public void removeRegisterGroups(IRegisterGroupDMContext[] groups, RequestMonitor rm);
+
+ /**
+ * Returns a boolean indicating if it is allowed to restore to the default groups
+ * @param ctx
+ * @param rm
+ */
+ public void canRestoreDefaultGroups(IDMContext ctx, DataRequestMonitor<Boolean> rm);
+
+ /**
+ * Remove all the user defined register groups and restore the default ones to their
+ * original state.
+ *
+ * @param rm - request monitor
+ */
+ public void restoreDefaultGroups(IDMContext selectionContext, RequestMonitor rm);
+
+}

Back to the top