1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Bug 415304 - project_loc, project_name and project_path variables in

launch configurations are resolved unreliably.

This change fixes string substitution for the GDB command file
attribute. A similar approach can be applied to other launch
configuration attributes too. 

Change-Id: I4e6447ccd8c652ad555b754daf040aba1c44cf3a
Reviewed-on: https://git.eclipse.org/r/15574
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Sergey Prigogin 2013-08-18 18:38:25 -07:00
parent 62c4e62ff3
commit 8f5e2ed1be
12 changed files with 575 additions and 48 deletions

View file

@ -119,6 +119,22 @@
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/debug/internal/core/DebugStringVariableSubstitutor.java" type="org.eclipse.cdt.debug.internal.core.DebugStringVariableSubstitutor">
<filter id="574619656">
<message_arguments>
<message_argument value="IStringVariableManager"/>
<message_argument value="DebugStringVariableSubstitutor"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/debug/internal/core/DebugStringVariableSubstitutor.java" type="org.eclipse.cdt.debug.internal.core.DebugStringVariableSubstitutor$ProjectVariable">
<filter id="574619656">
<message_arguments>
<message_argument value="IDynamicVariable"/>
<message_argument value="ProjectVariable"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/debug/internal/core/Trace.java" type="org.eclipse.cdt.debug.internal.core.Trace">
<filter id="574619656">
<message_arguments>

View file

@ -18,7 +18,7 @@ Export-Package: org.eclipse.cdt.debug.core,
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.core.sourcelookup,
org.eclipse.cdt.debug.internal.core;x-friends:="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.executables;x-internal:=true,
org.eclipse.cdt.debug.internal.core.model;x-internal:=true,

View file

@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.MessageFormat;
import java.util.Date;
import org.eclipse.cdt.core.CCorePlugin;
@ -39,6 +37,9 @@ import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IProcess;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.MessageFormat;
public class CDebugAdapter implements ICDIDebugger {
final ICDebugger fDebugger;
@ -59,12 +60,12 @@ public class CDebugAdapter implements ICDIDebugger {
public ICDISession createDebuggerSession(ILaunch launch, IBinaryObject exe, IProgressMonitor monitor) throws CoreException {
ILaunchConfiguration config = launch.getLaunchConfiguration();
if (exe == null) {
abort(InternalDebugCoreMessages.getString("CDebugAdapter.Program_file_not_specified"), null, //$NON-NLS-1$
abort(InternalDebugCoreMessages.CDebugAdapter_Program_file_not_specified, null,
ICDTLaunchConfigurationConstants.ERR_UNSPECIFIED_PROGRAM);
}
IFile[] exeFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(exe.getPath());
if (exeFile.length == 0) {
abort(InternalDebugCoreMessages.getString("CDebugAdapter.0"), null, -1); //$NON-NLS-1$
abort(InternalDebugCoreMessages.CDebugAdapter_0, null, -1);
}
int pid = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
String coreFile = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, (String)null);
@ -92,7 +93,7 @@ public class CDebugAdapter implements ICDIDebugger {
protected String renderDebuggerProcessLabel() {
String format = "{0} ({1})"; //$NON-NLS-1$
String timestamp = DateFormat.getInstance().format(new Date(System.currentTimeMillis()));
String message = InternalDebugCoreMessages.getString("CDebugAdapter.1"); //$NON-NLS-1$
String message = InternalDebugCoreMessages.CDebugAdapter_1;
return MessageFormat.format(format, message, timestamp);
}

View file

@ -239,7 +239,7 @@ public class CGlobalVariableManager implements ICGlobalVariableManager {
catch( IOException e ) {
ex = e;
}
abort( InternalDebugCoreMessages.getString( "CGlobalVariableManager.0" ), ex ); //$NON-NLS-1$
abort(InternalDebugCoreMessages.CGlobalVariableManager_0, ex);
}
private void initialize() {

View file

@ -136,7 +136,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
return;
}
abort( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.3" ), null ); //$NON-NLS-1$
abort(InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_3, null);
}
/**
@ -157,7 +157,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
CDebugTarget target = getDebugTarget();
if (target == null) {
throw new DebugException(new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), DebugException.REQUEST_FAILED,
InternalDebugCoreMessages.getString("CMemoryBlockRetrievalExtension.CDebugTarget_not_available"), null)); //$NON-NLS-1$
InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_CDebugTarget_not_available, null));
}
IAddressFactory addrFactory = target.getAddressFactory();
if (addrFactory instanceof IAddressFactory2) {
@ -280,11 +280,11 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
}
else {
msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.1" ), new String[] { expression } ); //$NON-NLS-1$
msg = MessageFormat.format(InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_1, expression);
}
}
else {
msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.2" ), new String[] { expression } ); //$NON-NLS-1$
msg = MessageFormat.format(InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_2, expression);
}
}
}
@ -293,7 +293,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
msg = e.getMessage();
}
catch( NumberFormatException e ) {
msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.0" ), new String[] { expression } ); //$NON-NLS-1$
msg = MessageFormat.format(InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_0, expression);
}
finally {
if (exp != null) {
@ -439,7 +439,9 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
// minimum is "<space>:<expression>"
if ((index == -1) || (index == str.length()-1)) {
IStatus s = new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.5" ), null ); //$NON-NLS-1$
IStatus s = new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(),
CDebugCorePlugin.INTERNAL_ERROR,
InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_invalid_encoded_address, null);
throw new CoreException( s );
}
@ -474,7 +476,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
};
}
catch (CDIException exc) {
IStatus s = new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.invalid_encoded_addresses" ), exc); //$NON-NLS-1$
IStatus s = new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.CMemoryBlockRetrievalExtension_invalid_encoded_address, exc);
throw new CoreException(s);
}

View file

@ -257,11 +257,11 @@ public class CRegisterManager {
private void initializeFromMemento( String memento ) throws CoreException {
Node node = DebugPlugin.parseDocument( memento );
if ( node.getNodeType() != Node.ELEMENT_NODE ) {
abort( InternalDebugCoreMessages.getString( "CRegisterManager.0" ), null ); //$NON-NLS-1$
abort(InternalDebugCoreMessages.CRegisterManager_0, null);
}
Element element = (Element)node;
if ( !ELEMENT_REGISTER_GROUP_LIST.equals( element.getNodeName() ) ) {
abort( InternalDebugCoreMessages.getString( "CRegisterManager.1" ), null ); //$NON-NLS-1$
abort(InternalDebugCoreMessages.CRegisterManager_1, null);
}
Node childNode = element.getFirstChild();
while( childNode != null ) {

View file

@ -51,7 +51,8 @@ public class DebugConfiguration implements ICDebugConfiguration {
if (debugger instanceof ICDebugger) {
return (ICDebugger)debugger;
}
throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), -1, InternalDebugCoreMessages.getString("DebugConfiguration.0"), null)); //$NON-NLS-1$
throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), -1,
InternalDebugCoreMessages.DebugConfiguration_0, null));
}
@Override

View file

@ -0,0 +1,190 @@
/*******************************************************************************
* Copyright (c) 2013 Google, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.IDynamicVariable;
import org.eclipse.core.variables.IStringVariable;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.IValueVariable;
import org.eclipse.core.variables.IValueVariableListener;
import org.eclipse.core.variables.VariablesPlugin;
/**
* String variable substitutor that resolves project_name, project_loc and project_path variables
* in the context of the given project. Resolution of all other variables is delegated to
* the default string variable manager.
*/
public class DebugStringVariableSubstitutor implements IStringVariableManager {
private static class ProjectVariable implements IDynamicVariable {
final String name;
final IProject project;
final String description;
ProjectVariable(String name, String description, IProject project) {
this.name = name;
this.description = description;
this.project = project;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getValue(String argument) throws CoreException {
IProject project = this.project;
if (argument != null) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IPath path = Path.fromOSString(argument);
project = path.isEmpty() ? null : root.getProject(path.segment(0));
}
if (project == null)
return null;
if (name.endsWith("_name")) //$NON-NLS-1$
return project.getName();
if (name.endsWith("_loc")) //$NON-NLS-1$
return project.getLocation().toOSString();
if (name.endsWith("_path")) //$NON-NLS-1$
return project.getProjectRelativePath().toString();
return null;
}
@Override
public boolean supportsArgument() {
return true;
}
}
private final IStringVariableManager variableManager;
private final IProject project;
/**
* Creates a variable substitutor that resolves project_name, project_loc and project_path
* variables in the context of the given project.
*
* @param project the project used to resolve project_name, project_loc and project_path
* variables. If {@code null}, the project is determined based on the current selection.
*/
public DebugStringVariableSubstitutor(IProject project) {
this.variableManager = VariablesPlugin.getDefault().getStringVariableManager();
this.project = project;
}
/**
* Creates a variable substitutor that resolves project_name, project_loc and project_path
* variables in the context of the given project.
*
* @param projectName the name of the project used to resolve project_name, project_loc and
* project_path variables. If {@code null}, the project is determined based on the current
* selection.
*/
public DebugStringVariableSubstitutor(String projectName) {
this(projectName == null ? null : ResourcesPlugin.getWorkspace().getRoot().getProject(projectName));
}
public IStringVariable[] getVariables() {
IStringVariable[] variables = variableManager.getVariables();
for (int i = 0; i < variables.length; i++) {
IStringVariable var = variables[i];
if (var instanceof IDynamicVariable)
variables[i] = substituteVariable((IDynamicVariable) var);
}
return variables;
}
public IValueVariable[] getValueVariables() {
return variableManager.getValueVariables();
}
public IValueVariable getValueVariable(String name) {
return variableManager.getValueVariable(name);
}
public IDynamicVariable[] getDynamicVariables() {
IDynamicVariable[] variables = variableManager.getDynamicVariables();
for (int i = 0; i < variables.length; i++) {
variables[i] = substituteVariable(variables[i]);
}
return variables;
}
public IDynamicVariable getDynamicVariable(String name) {
IDynamicVariable var = variableManager.getDynamicVariable(name);
return substituteVariable(var);
}
private IDynamicVariable substituteVariable(IDynamicVariable var) {
String name = var.getName();
if ("project_loc".equals(name) || "project_name".equals(name) || "project_path".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return new ProjectVariable(name, var.getDescription(), project);
}
return var;
}
public String getContributingPluginId(IStringVariable variable) {
return variableManager.getContributingPluginId(variable);
}
public String performStringSubstitution(String expression) throws CoreException {
return performStringSubstitution(expression, true);
}
public String performStringSubstitution(String expression, boolean reportUndefinedVariables)
throws CoreException {
return new StringSubstitutionEngine().performStringSubstitution(expression,
reportUndefinedVariables, true, this);
}
public void validateStringVariables(String expression) throws CoreException {
new StringSubstitutionEngine().validateStringVariables(expression, this);
}
public IValueVariable newValueVariable(String name, String description) {
return variableManager.newValueVariable(name, description);
}
public IValueVariable newValueVariable(String name, String description, boolean readOnly,
String value) {
return variableManager.newValueVariable(name, description, readOnly, value);
}
public void addVariables(IValueVariable[] variables) throws CoreException {
variableManager.addVariables(variables);
}
public void removeVariables(IValueVariable[] variables) {
variableManager.removeVariables(variables);
}
public void addValueVariableListener(IValueVariableListener listener) {
variableManager.addValueVariableListener(listener);
}
public void removeValueVariableListener(IValueVariableListener listener) {
variableManager.removeValueVariableListener(listener);
}
public String generateVariableExpression(String varName, String arg) {
return variableManager.generateVariableExpression(varName, arg);
}
}

View file

@ -6,28 +6,38 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* QNX Software Systems - Initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.eclipse.core.internal.variables.VariablesMessages;
import org.eclipse.osgi.util.NLS;
public class InternalDebugCoreMessages {
private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.internal.core.InternalDebugCoreMessages";//$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle( BUNDLE_NAME );
public class InternalDebugCoreMessages extends NLS {
public static String CGlobalVariableManager_0;
public static String CMemoryBlockRetrievalExtension_0;
public static String CMemoryBlockRetrievalExtension_1;
public static String CMemoryBlockRetrievalExtension_2;
public static String CMemoryBlockRetrievalExtension_3;
public static String CMemoryBlockRetrievalExtension_4;
public static String CMemoryBlockRetrievalExtension_invalid_encoded_address;
public static String CMemoryBlockRetrievalExtension_CDebugTarget_not_available;
public static String DebugConfiguration_0;
public static String CDebugAdapter_0;
public static String CDebugAdapter_1;
public static String CDebugAdapter_Program_file_not_specified;
public static String CRegisterManager_0;
public static String CRegisterManager_1;
public static String StringSubstitutionEngine_undefined_variable;
public static String StringSubstitutionEngine_unexpected_argument;
private InternalDebugCoreMessages() {
}
public static String getString( String key ) {
try {
return RESOURCE_BUNDLE.getString( key );
}
catch( MissingResourceException e ) {
return '!' + key + '!';
}
static {
// Load message values from a bundle file.
NLS.initializeMessages(InternalDebugCoreMessages.class.getName(), VariablesMessages.class);
}
}

View file

@ -7,18 +7,21 @@
#
# Contributors:
# QNX Software Systems - initial API and implementation
# Sergey Prigogin (Google)
###############################################################################
CGlobalVariableManager.0=Invalid global variables data.
CMemoryBlockRetrievalExtension.0=Expression ''{0}'' evaluated to invalid address value.
CMemoryBlockRetrievalExtension.1=Invalid expression type: ''{0}''
CMemoryBlockRetrievalExtension.2=Invalid expression: ''{0}''
CMemoryBlockRetrievalExtension.3=Memory initialization: invalid memento.
CMemoryBlockRetrievalExtension.4=Invalid address: ''{0}''
CMemoryBlockRetrievalExtension.invalid_encoded_addresses=Format of encoded address is invalid.
CMemoryBlockRetrievalExtension.CDebugTarget_not_available=Request cannot be handled at this time, probably because debug session has terminated.
DebugConfiguration.0=This debugger no longer supports this operation
CDebugAdapter.0=This debugger does not support debugging external files
CDebugAdapter.1=Debugger Process
CDebugAdapter.Program_file_not_specified=Program file not specified
CRegisterManager.0=Unable to restore register groups - invalid memento.
CRegisterManager.1=Unable to restore register groups - expecting register group list element.
CGlobalVariableManager_0=Invalid global variables data.
CMemoryBlockRetrievalExtension_0=Expression ''{0}'' evaluated to invalid address value.
CMemoryBlockRetrievalExtension_1=Invalid expression type: ''{0}''
CMemoryBlockRetrievalExtension_2=Invalid expression: ''{0}''
CMemoryBlockRetrievalExtension_3=Memory initialization: invalid memento.
CMemoryBlockRetrievalExtension_4=Invalid address: ''{0}''
CMemoryBlockRetrievalExtension_invalid_encoded_address=Format of encoded address is invalid.
CMemoryBlockRetrievalExtension_CDebugTarget_not_available=Request cannot be handled at this time, probably because debug session has terminated.
DebugConfiguration_0=This debugger no longer supports this operation
CDebugAdapter_0=This debugger does not support debugging external files
CDebugAdapter_1=Debugger Process
CDebugAdapter_Program_file_not_specified=Program file not specified
CRegisterManager_0=Unable to restore register groups - invalid memento.
CRegisterManager_1=Unable to restore register groups - expecting register group list element.
StringSubstitutionEngine_undefined_variable=Reference to undefined variable {0}
StringSubstitutionEngine_unexpected_argument=Variable {0} does not accept arguments

View file

@ -0,0 +1,303 @@
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.IDynamicVariable;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.IValueVariable;
import org.eclipse.osgi.util.NLS;
/**
* Performs string substitution for context and value variables.
* A clone of {@link org.eclipse.core.internal.variables.StringSubstitutionEngine}.
*/
public class StringSubstitutionEngine {
// Delimiters.
private static final String VARIABLE_START = "${"; //$NON-NLS-1$
private static final char VARIABLE_END = '}';
private static final char VARIABLE_ARG = ':';
// Parsing states.
private static final int SCAN_FOR_START = 0;
private static final int SCAN_FOR_END = 1;
/**
* Resulting string
*/
private StringBuilder fResult;
/**
* Whether substitutions were performed
*/
private boolean fSubs;
/**
* Stack of variables to resolve
*/
private Stack<VariableReference> fStack;
class VariableReference {
// The text inside the variable reference.
private StringBuilder fText;
public VariableReference() {
fText = new StringBuilder();
}
public void append(String text) {
fText.append(text);
}
public String getText() {
return fText.toString();
}
}
/**
* Performs recursive string substitution and returns the resulting string.
*
* @param expression expression to resolve
* @param reportUndefinedVariables whether to report undefined variables as an error
* @param resolveVariables if the variables should be resolved during the substitution
* @param manager registry of variables
* @return the resulting string with all variables recursively substituted
* @exception CoreException if unable to resolve a referenced variable or if a cycle exists
* in referenced variables
*/
public String performStringSubstitution(String expression, boolean reportUndefinedVariables,
boolean resolveVariables, IStringVariableManager manager) throws CoreException {
substitute(expression, reportUndefinedVariables, resolveVariables, manager);
List<HashSet<String>> resolvedVariableSets = new ArrayList<HashSet<String>>();
while (fSubs) {
HashSet<String> resolved = substitute(fResult.toString(), reportUndefinedVariables, true, manager);
for (int i = resolvedVariableSets.size(); --i >= 0;) {
HashSet<String> prevSet = resolvedVariableSets.get(i);
if (prevSet.equals(resolved)) {
HashSet<String> conflictingSet = new HashSet<String>();
for (HashSet<String> set : resolvedVariableSets) {
conflictingSet.addAll(set);
}
StringBuilder problemVariableList = new StringBuilder();
for (String var : conflictingSet) {
problemVariableList.append(var.toString());
problemVariableList.append(", "); //$NON-NLS-1$
}
problemVariableList.setLength(problemVariableList.length() - 2); // Truncate the last ", "
throw new CoreException(new Status(IStatus.ERROR,
CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR,
NLS.bind(InternalDebugCoreMessages.StringSubstitutionEngine_undefined_variable, problemVariableList.toString()), null));
}
}
resolvedVariableSets.add(resolved);
}
return fResult.toString();
}
/**
* Performs recursive string validation to ensure that all of the variables
* contained in the expression exist.
*
* @param expression expression to validate
* @param manager registry of variables
* @exception CoreException if a referenced variable does not exist or if a cycle exists
* in referenced variables
*/
public void validateStringVariables(String expression, IStringVariableManager manager)
throws CoreException {
performStringSubstitution(expression, true, false, manager);
}
/**
* Makes a substitution pass of the given expression returns a Set of the variables that were
* resolved in this pass.
*
* @param expression source expression
* @param reportUndefinedVariables whether to report undefined variables as an error
* @param resolveVariables whether to resolve the value of any variables
* @param manager the {@link IStringVariableManager} to use for the substitution
* @return the set of {@link String}s resolved from the given expression
* @exception CoreException if unable to resolve a variable
*/
private HashSet<String> substitute(String expression, boolean reportUndefinedVariables,
boolean resolveVariables, IStringVariableManager manager) throws CoreException {
fResult = new StringBuilder(expression.length());
fStack = new Stack<VariableReference>();
fSubs = false;
HashSet<String> resolvedVariables = new HashSet<String>();
int pos = 0;
int state = SCAN_FOR_START;
while (pos < expression.length()) {
switch (state) {
case SCAN_FOR_START:
int start = expression.indexOf(VARIABLE_START, pos);
if (start >= 0) {
int length = start - pos;
// Copy non-variable text to the result.
if (length > 0) {
fResult.append(expression.substring(pos, start));
}
pos = start + 2;
state = SCAN_FOR_END;
fStack.push(new VariableReference());
} else {
// Done - no more variables.
fResult.append(expression.substring(pos));
pos = expression.length();
}
break;
case SCAN_FOR_END:
// Be careful of nested variables.
start = expression.indexOf(VARIABLE_START, pos);
int end = expression.indexOf(VARIABLE_END, pos);
if (end < 0) {
// Variables are not completed.
VariableReference tos = fStack.peek();
tos.append(expression.substring(pos));
pos = expression.length();
} else {
if (start >= 0 && start < end) {
// Start of a nested variable.
int length = start - pos;
if (length > 0) {
VariableReference tos = fStack.peek();
tos.append(expression.substring(pos, start));
}
pos = start + 2;
fStack.push(new VariableReference());
} else {
// End of variable reference.
VariableReference tos = fStack.pop();
String substring = expression.substring(pos, end);
tos.append(substring);
resolvedVariables.add(substring);
pos = end + 1;
String value= resolve(tos, reportUndefinedVariables, resolveVariables, manager);
if (value == null) {
value = ""; //$NON-NLS-1$
}
if (fStack.isEmpty()) {
// Append to result.
fResult.append(value);
state = SCAN_FOR_START;
} else {
// Append to previous variable.
tos = fStack.peek();
tos.append(value);
}
}
}
break;
}
}
// Process incomplete variable references.
while (!fStack.isEmpty()) {
VariableReference tos = fStack.pop();
if (fStack.isEmpty()) {
fResult.append(VARIABLE_START);
fResult.append(tos.getText());
} else {
VariableReference var = fStack.peek();
var.append(VARIABLE_START);
var.append(tos.getText());
}
}
return resolvedVariables;
}
/**
* Resolve and return the value of the given variable reference, possibly {@code null}.
*
* @param var the {@link VariableReference} to try and resolve
* @param reportUndefinedVariables whether to report undefined variables as an error
* @param resolveVariables whether to resolve the variables value or just to validate that
* this variable is valid
* @param manager variable registry
* @return variable value, possibly {@code null}
* @exception CoreException if unable to resolve a value
*/
private String resolve(VariableReference var, boolean reportUndefinedVariables,
boolean resolveVariables, IStringVariableManager manager) throws CoreException {
String text = var.getText();
int pos = text.indexOf(VARIABLE_ARG);
String name = null;
String arg = null;
if (pos > 0) {
name = text.substring(0, pos);
pos++;
if (pos < text.length()) {
arg = text.substring(pos);
}
} else {
name = text;
}
IValueVariable valueVariable = manager.getValueVariable(name);
if (valueVariable == null) {
IDynamicVariable dynamicVariable = manager.getDynamicVariable(name);
if (dynamicVariable == null) {
// No variables with the given name.
if (reportUndefinedVariables) {
throw new CoreException(new Status(IStatus.ERROR,
CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR,
NLS.bind(InternalDebugCoreMessages.StringSubstitutionEngine_undefined_variable, name), null));
}
// Leave as is.
return getOriginalVarText(var);
}
if (resolveVariables) {
fSubs = true;
return dynamicVariable.getValue(arg);
}
// Leave as is.
return getOriginalVarText(var);
}
if (arg == null) {
if (resolveVariables) {
fSubs = true;
return valueVariable.getValue();
}
// Leave as is.
return getOriginalVarText(var);
}
// Error - an argument specified for a value variable.
throw new CoreException(new Status(IStatus.ERROR,
CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR,
NLS.bind(InternalDebugCoreMessages.StringSubstitutionEngine_unexpected_argument,
valueVariable.getName()), null));
}
private String getOriginalVarText(VariableReference var) {
StringBuilder res = new StringBuilder(var.getText());
res.insert(0, VARIABLE_START);
res.append(VARIABLE_END);
return res.toString();
}
}

View file

@ -23,6 +23,7 @@ import java.util.Map;
import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.model.IConnectHandler;
import org.eclipse.cdt.debug.internal.core.DebugStringVariableSubstitutor;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
@ -51,7 +52,6 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunch;
public class FinalLaunchSequence extends ReflectionSequence {
@ -298,7 +298,8 @@ public class FinalLaunchSequence extends ReflectionSequence {
String gdbinitFile = fGDBBackend.getGDBInitFile();
if (gdbinitFile != null && gdbinitFile.length() > 0) {
final String expandedGDBInitFile = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(gdbinitFile);
String projectName = (String) fAttributes.get(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME);
final String expandedGDBInitFile = new DebugStringVariableSubstitutor(projectName).performStringSubstitution(gdbinitFile);
fCommandControl.queueCommand(
fCommandFactory.createCLISource(fCommandControl.getContext(), expandedGDBInitFile),