/*******************************************************************************
* Copyright (c) 2005, 2009 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
* Ken Ryall (Nokia) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=118894
* IBM Corporation
*******************************************************************************/
package org.eclipse.cdt.launch.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.ICDebugConfiguration;
import org.eclipse.cdt.debug.core.ICDebugConstants;
import org.eclipse.cdt.debug.ui.ICDebuggerPage;
import org.eclipse.cdt.launch.LaunchUtils;
import org.eclipse.cdt.launch.internal.ui.AbstractCDebuggerTab;
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.MessageFormat;
public class CDebuggerTab extends AbstractCDebuggerTab {
/**
* Tab identifier used for ordering of tabs added using the
* <code>org.eclipse.debug.ui.launchConfigurationTabs</code>
* extension point.
*
* @since 6.0
*/
public static final String TAB_ID = "org.eclipse.cdt.cdi.launch.debuggerTab"; //$NON-NLS-1$
public class AdvancedDebuggerOptionsDialog extends Dialog {
private Button fVarBookKeeping;
private Button fRegBookKeeping;
/**
* Constructor for AdvancedDebuggerOptionsDialog.
*/
protected AdvancedDebuggerOptionsDialog(Shell parentShell) {
super(parentShell);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite)super.createDialogArea(parent);
Group group = new Group(composite, SWT.NONE);
group.setText(LaunchMessages.CDebuggerTab_Automatically_track_values_of);
GridLayout layout = new GridLayout();
group.setLayout(layout);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fVarBookKeeping = new Button(group, SWT.CHECK);
fVarBookKeeping.setText(LaunchMessages.CDebuggerTab_Variables);
fRegBookKeeping = new Button(group, SWT.CHECK);
fRegBookKeeping.setText(LaunchMessages.CDebuggerTab_Registers);
initialize();
return composite;
}
protected void okPressed() {
saveValues();
super.okPressed();
}
private void initialize() {
Map attr = getAdvancedAttributes();
Object varBookkeeping = attr.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING);
fVarBookKeeping.setSelection((varBookkeeping instanceof Boolean) ? !((Boolean)varBookkeeping).booleanValue() : true);
Object regBookkeeping = attr.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING);
fRegBookKeeping.setSelection((regBookkeeping instanceof Boolean) ? !((Boolean)regBookkeeping).booleanValue() : true);
}
private void saveValues() {
Map attr = getAdvancedAttributes();
Boolean varBookkeeping = Boolean.valueOf(!fVarBookKeeping.getSelection());
attr.put(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING, varBookkeeping);
Boolean regBookkeeping = Boolean.valueOf(!fRegBookKeeping.getSelection());
attr.put(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, regBookkeeping);
update();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(LaunchMessages.CDebuggerTab_Advanced_Options_Dialog_Title);
}
}
final protected boolean fAttachMode;
protected Button fAdvancedButton;
protected Button fStopInMain;
protected Text fStopInMainSymbol;
protected Button fAttachButton;
private Map fAdvancedAttributes = new HashMap(5);
private ScrolledComposite fContainer;
private Composite fContents;
public CDebuggerTab(boolean attachMode) {
fAttachMode = attachMode;
// If the default debugger has not been set, use the MI debugger.
// The MI plug-in also does this, but it may not have been loaded yet. Bug 158391.
ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDefaultDebugConfiguration();
if (dc == null) {
CDebugCorePlugin.getDefault().getPluginPreferences().setDefault(ICDebugConstants.PREF_DEFAULT_DEBUGGER_TYPE, "org.eclipse.cdt.debug.mi.core.CDebuggerNew"); //$NON-NLS-1$
}
}
@Override
public String getId() {
return TAB_ID;
}
public void createControl(Composite parent) {
fContainer = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL);
fContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
fContainer.setLayout(new FillLayout());
fContainer.setExpandHorizontal(true);
fContainer.setExpandVertical(true);
fContents = new Composite(fContainer, SWT.NONE);
setControl(fContainer);
LaunchUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(getControl(),
ICDTLaunchHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_DEBBUGER_TAB);
int numberOfColumns = (fAttachMode) ? 2 : 1;
GridLayout layout = new GridLayout(numberOfColumns, false);
fContents.setLayout(layout);
GridData gd = new GridData(GridData.BEGINNING, GridData.CENTER, true, false);
fContents.setLayoutData(gd);
createDebuggerCombo(fContents, (fAttachMode) ? 1 : 2);
createOptionsComposite(fContents);
createDebuggerGroup(fContents, 2);
fContainer.setContent(fContents);
}
protected void loadDebuggerComboBox(ILaunchConfiguration config, String selection) {
ICDebugConfiguration[] debugConfigs;
String configPlatform = getPlatform(config);
debugConfigs = CDebugCorePlugin.getDefault().getActiveDebugConfigurations();
Arrays.sort(debugConfigs, new Comparator<ICDebugConfiguration>() {
public int compare(ICDebugConfiguration c1, ICDebugConfiguration c2) {
return Collator.getInstance().compare(c1.getName(), c2.getName());
}
});
List list = new ArrayList();
String mode;
if (fAttachMode) {
mode = ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH;
} else {
mode = ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN;
}
if (selection.equals("")) { //$NON-NLS-1$
ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
if (dc == null) {
CDebugCorePlugin.getDefault().saveDefaultDebugConfiguration("org.eclipse.cdt.debug.mi.core.CDebuggerNew");
dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
}
if (dc != null)
selection = dc.getID();
}
String defaultSelection = selection;
for (int i = 0; i < debugConfigs.length; i++) {
if (debugConfigs[i].supportsMode(mode)) {
String debuggerPlatform = debugConfigs[i].getPlatform();
if (validatePlatform(config, debugConfigs[i])) {
list.add(debugConfigs[i]);
// select first exact matching debugger for platform or
// requested selection
if ((defaultSelection.equals("") && debuggerPlatform.equalsIgnoreCase(configPlatform))) { //$NON-NLS-1$
defaultSelection = debugConfigs[i].getID();
}
}
}
}
// if no selection meaning nothing in config the force initdefault on
// tab
setInitializeDefault(selection.equals("") ? true : false); //$NON-NLS-1$
loadDebuggerCombo((ICDebugConfiguration[])list.toArray(new ICDebugConfiguration[list.size()]), defaultSelection);
}
protected void updateComboFromSelection() {
super.updateComboFromSelection();
initializeCommonControls(getLaunchConfiguration());
}
public void setDefaults(ILaunchConfigurationWorkingCopy config) {
super.setDefaults(config);
if (fAttachMode) {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH);
} else {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT);
}
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING, false);
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, false);
// Set the default debugger based on the active toolchain on the project (if possible)
String defaultDebugger = null;
try {
String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, "");
if (projectName.length() > 0) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project);
ICConfigurationDescription configDesc = projDesc.getActiveConfiguration();
String configId = configDesc.getId();
ICDebugConfiguration[] debugConfigs = CDebugCorePlugin.getDefault().getActiveDebugConfigurations();
outer: for (int i = 0; i < debugConfigs.length; ++i) {
ICDebugConfiguration debugConfig = debugConfigs[i];
String[] patterns = debugConfig.getSupportedBuildConfigPatterns();
if (patterns != null) {
for (int j = 0; j < patterns.length; ++j) {
if (configId.matches(patterns[j])) {
defaultDebugger = debugConfig.getID();
break outer;
}
}
}
}
}
} catch (CoreException e) {
}
if (defaultDebugger == null) {
ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
if (dc != null) {
defaultDebugger = dc.getID();
}
}
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, defaultDebugger);
}
public void initializeFrom(ILaunchConfiguration config) {
setInitializing(true);
super.initializeFrom(config);
try {
String id = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, ""); //$NON-NLS-1$
loadDebuggerComboBox(config, id);
initializeCommonControls(config);
} catch (CoreException e) {
}
setInitializing(false);
}
public void performApply(ILaunchConfigurationWorkingCopy config) {
super.performApply(config);
if (fAttachMode) {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH);
} else {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, fStopInMain.getSelection());
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, fStopInMainSymbol.getText());
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
}
applyAdvancedAttributes(config);
}
public boolean isValid(ILaunchConfiguration config) {
if (!validateDebuggerConfig(config)) {
return false;
}
ICDebugConfiguration debugConfig = getDebugConfig();
String mode = fAttachMode
? ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH
: ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN;
if (!debugConfig.supportsMode(mode)) {
setErrorMessage(MessageFormat.format(LaunchMessages.CDebuggerTab_Mode_not_supported, new String[]{mode}));
return false;
}
if (fStopInMain != null && fStopInMainSymbol != null) {
// The "Stop on startup at" field must not be empty
String mainSymbol = fStopInMainSymbol.getText().trim();
if (fStopInMain.getSelection() && mainSymbol.length() == 0) {
setErrorMessage(LaunchMessages.CDebuggerTab_Stop_on_startup_at_can_not_be_empty);
return false;
}
}
if (super.isValid(config) == false) {
return false;
}
return true;
}
protected boolean validatePlatform(ILaunchConfiguration config, ICDebugConfiguration debugConfig) {
String configPlatform = getPlatform(config);
String debuggerPlatform = debugConfig.getPlatform();
return (debuggerPlatform.equals("*") || debuggerPlatform.equalsIgnoreCase(configPlatform)); //$NON-NLS-1$
}
protected boolean validateCPU(ILaunchConfiguration config, ICDebugConfiguration debugConfig) {
IBinaryObject binaryFile = null;
try {
binaryFile = getBinary(config);
} catch (CoreException e) {
setErrorMessage(e.getLocalizedMessage());
}
String projectCPU = ICDebugConfiguration.CPU_NATIVE;
if (binaryFile != null) {
projectCPU = binaryFile.getCPU();
}
return debugConfig.supportsCPU(projectCPU);
}
protected IBinaryObject getBinary(ILaunchConfiguration config) throws CoreException {
String programName = null;
String projectName = null;
try {
projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
programName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String)null);
} catch (CoreException e) {
}
if (programName != null) {
return LaunchUtils.getBinary(programName, projectName);
}
return null;
}
protected boolean validateDebuggerConfig(ILaunchConfiguration config) {
ICDebugConfiguration debugConfig = getDebugConfig();
if (debugConfig == null) {
setErrorMessage(LaunchMessages.CDebuggerTab_No_debugger_available);
return false;
}
// We do not validate platform and CPU compatibility to avoid accidentally disabling
// a valid configuration. It's much better to let an incompatible configuration through
// than to disable a valid one.
return true;
}
/**
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog()
*/
protected void update() {
if (!isInitializing()) {
super.updateLaunchConfigurationDialog();
}
}
protected void createOptionsComposite(Composite parent) {
Composite optionsComp = new Composite(parent, SWT.NONE);
int numberOfColumns = (fAttachMode) ? 1 : 3;
GridLayout layout = new GridLayout(numberOfColumns, false);
optionsComp.setLayout(layout);
optionsComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, true, false, 1, 1));
if (fAttachMode == false) {
fStopInMain = createCheckButton(optionsComp, LaunchMessages.CDebuggerTab_Stop_at_main_on_startup);
fStopInMain.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
fStopInMainSymbol.setEnabled(fStopInMain.getSelection());
update();
}
});
fStopInMainSymbol = new Text(optionsComp, SWT.SINGLE | SWT.BORDER);
final GridData gridData = new GridData(GridData.FILL, GridData.CENTER, false, false);
gridData.widthHint = 100;
fStopInMainSymbol.setLayoutData(gridData);
fStopInMainSymbol.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent evt) {
update();
}
});
fStopInMainSymbol.getAccessible().addAccessibleListener(
new AccessibleAdapter() {
public void getName(AccessibleEvent e) {
e.result = LaunchMessages.CDebuggerTab_Stop_at_main_on_startup;
}
}
);
}
fAdvancedButton = createPushButton(optionsComp, LaunchMessages.CDebuggerTab_Advanced, null);
((GridData)fAdvancedButton.getLayoutData()).horizontalAlignment = GridData.END;
fAdvancedButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Dialog dialog = new AdvancedDebuggerOptionsDialog(getShell());
dialog.open();
}
});
}
protected Map getAdvancedAttributes() {
return fAdvancedAttributes;
}
private void initializeAdvancedAttributes(ILaunchConfiguration config) {
Map attr = getAdvancedAttributes();
try {
Boolean varBookkeeping = (config.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING, false))
? Boolean.TRUE
: Boolean.FALSE;
attr.put(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING, varBookkeeping);
} catch (CoreException e) {
}
try {
Boolean regBookkeeping = (config.getAttribute(
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, false))
? Boolean.TRUE
: Boolean.FALSE;
attr.put(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, regBookkeeping);
} catch (CoreException e) {
}
}
private void applyAdvancedAttributes(ILaunchConfigurationWorkingCopy config) {
Map attr = getAdvancedAttributes();
Object varBookkeeping = attr.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING);
if (varBookkeeping instanceof Boolean)
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING,
((Boolean)varBookkeeping).booleanValue());
Object regBookkeeping = attr.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING);
if (regBookkeeping instanceof Boolean)
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING,
((Boolean)regBookkeeping).booleanValue());
}
protected Shell getShell() {
return super.getShell();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose()
*/
public void dispose() {
getAdvancedAttributes().clear();
ICDebuggerPage debuggerPage = getDynamicTab();
if (debuggerPage != null)
debuggerPage.dispose();
super.dispose();
}
protected void initializeCommonControls(ILaunchConfiguration config) {
try {
if (!fAttachMode) {
fStopInMain.setSelection(config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT));
fStopInMainSymbol.setText(config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT));
fStopInMainSymbol.setEnabled(fStopInMain.getSelection());
}
initializeAdvancedAttributes(config);
} catch (CoreException e) {
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.launch.internal.ui.AbstractCDebuggerTab#setInitializeDefault(boolean)
*/
protected void setInitializeDefault(boolean init) {
super.setInitializeDefault(init);
}
protected void contentsChanged() {
fContainer.setMinSize(fContents.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
}