/******************************************************************************* * Copyright (c) 2005, 2007 Intel 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: * Intel Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.macros; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.managedbuilder.core.IBuildObject; import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IInputType; import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; import org.eclipse.cdt.managedbuilder.core.IManagedProject; import org.eclipse.cdt.managedbuilder.core.IOutputType; import org.eclipse.cdt.managedbuilder.core.IResourceInfo; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; import org.eclipse.cdt.managedbuilder.macros.IReservedMacroNameSupplier; import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver; import org.eclipse.cdt.utils.cdtvariables.IVariableContextInfo; import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor; import org.eclipse.core.resources.IResource; /** * This substitutor resolves all macro references except for the environment macro references * If a user has chosen to keep those macros in the buildfile, the environment macro references * are converted to the buildfile variable references, otherwise those macros are also resolved * * @see org.eclipse.cdt.managedbuilder.internal.macros#IMacroSubstitutor * @since 3.0 */ public class BuildfileMacroSubstitutor extends SupplierBasedCdtVariableSubstitutor { private static final String PATTERN_MACRO_NAME = "="; //$NON-NLS-1$ private IConfiguration fConfiguration; private IBuilder fBuilder; private HashSet<String> fCaseInsensitiveReferencedNames; private ICdtVariableManager fVarMngr; private ICConfigurationDescription fCfgDes; private class DefaultReservedMacroNameSupplier implements IReservedMacroNameSupplier{ String fReservedNames[]; public DefaultReservedMacroNameSupplier(IConfiguration configuration){ IBuilder builder = configuration.getToolChain().getBuilder(); String reservedNames[] = builder.getReservedMacroNames(); String buildVars[] = getConfigurationReservedNames(configuration); if(reservedNames == null || reservedNames.length == 0) fReservedNames = buildVars; else if(buildVars == null || buildVars.length == 0) fReservedNames = reservedNames; else { fReservedNames = new String[reservedNames.length + buildVars.length]; System.arraycopy(reservedNames,0,fReservedNames,0,reservedNames.length); System.arraycopy(buildVars,0,fReservedNames,reservedNames.length,buildVars.length); } } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.macros.IReservedMacroNameSupplier#isReservedName(java.lang.String, org.eclipse.cdt.managedbuilder.core.IConfiguration) */ public boolean isReservedName(String macroName, IConfiguration configuration) { if(fReservedNames != null && fReservedNames.length > 0){ for(int i = 0; i < fReservedNames.length; i++){ Pattern p = Pattern.compile(fReservedNames[i]); Matcher m = p.matcher(macroName); if(m.matches()) return true; } } return false; } protected String[] getConfigurationReservedNames(IConfiguration configuration){ ITool tools[] = configuration.getFilteredTools(); if(tools != null){ Set<String> set = new HashSet<String>(); for(int i = 0; i < tools.length; i++){ IOutputType ots[] = tools[i].getOutputTypes(); if(ots != null){ for(int j = 0; j < ots.length; j++){ String varName = ots[j].getBuildVariable(); if(varName != null){ set.add(varName); } } } IInputType its[] = tools[i].getInputTypes(); if(its != null){ for(int j = 0; j < its.length; j++){ String varName = its[j].getBuildVariable(); if(varName != null){ set.add(varName); } } } } return set.toArray(new String[set.size()]); } return null; } } // public BuildfileMacroSubstitutor(int contextType, Object contextData, String inexistentMacroValue, String listDelimiter){ // super(contextType, contextData, inexistentMacroValue, listDelimiter); // init(); // } public BuildfileMacroSubstitutor(IBuilder builder, IMacroContextInfo contextInfo, String inexistentMacroValue, String listDelimiter){ super(contextInfo, inexistentMacroValue, listDelimiter); init(builder, contextInfo); } public BuildfileMacroSubstitutor(IMacroContextInfo contextInfo, String inexistentMacroValue, String listDelimiter){ this(null, contextInfo, inexistentMacroValue, listDelimiter); } private void init(IBuilder builder, IMacroContextInfo contextInfo){ if(contextInfo == null) return; fVarMngr = CCorePlugin.getDefault().getCdtVariableManager(); if(builder != null){ fBuilder = builder; fConfiguration = builder.getParent().getParent(); } else { IBuildObject[] bos = findConfigurationAndBuilderFromContext(contextInfo); if(bos != null){ fConfiguration = (IConfiguration)bos[0]; fBuilder = (IBuilder)bos[1]; } } if(fConfiguration != null){ fCfgDes = ManagedBuildManager.getDescriptionForConfiguration(fConfiguration); } } static IBuildObject[] findConfigurationAndBuilderFromContext(IMacroContextInfo contextInfo){ int type = contextInfo.getContextType(); IConfiguration cfg = null; IBuilder builder = null; switch(type){ case IBuildMacroProvider.CONTEXT_FILE: contextInfo = (IMacroContextInfo)contextInfo.getNext(); if(contextInfo == null) break; case IBuildMacroProvider.CONTEXT_OPTION: contextInfo = (IMacroContextInfo)contextInfo.getNext(); if(contextInfo == null) break; case IBuildMacroProvider.CONTEXT_CONFIGURATION:{ Object contextData = contextInfo.getContextData(); if(contextData instanceof IConfiguration){ cfg = (IConfiguration)contextData; builder = cfg.getBuilder(); } else if (contextData instanceof IBuilder){ builder = (IBuilder)contextData; cfg = builder.getParent().getParent(); } else if (contextData instanceof ITool) { ITool tool = (ITool)contextData; IResourceInfo rcInfo = tool.getParentResourceInfo(); if(rcInfo != null){ cfg = rcInfo.getParent(); if(cfg != null){ builder = cfg.getBuilder(); } } } } break; case IBuildMacroProvider.CONTEXT_PROJECT:{ Object contextData = contextInfo.getContextData(); if(contextData instanceof IManagedProject){ IResource rc = ((IManagedProject)contextData).getOwner(); if(rc != null){ IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(rc); cfg = info.getDefaultConfiguration(); builder = cfg.getBuilder(); } } } break; } if(cfg != null && builder != null) return new IBuildObject[]{cfg, builder}; return null; } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.internal.macros.DefaultMacroSubstitutor#resolveMacro(org.eclipse.cdt.managedbuilder.macros.IBuildMacro) */ @Override protected ResolvedMacro resolveMacro(ICdtVariable macro) throws CdtVariableException{ ResolvedMacro resolved = null; if(fConfiguration != null && fBuilder != null && fBuilder.keepEnvironmentVariablesInBuildfile() && fVarMngr.isEnvironmentVariable(macro, fCfgDes) && (!CdtVariableResolver.isStringListVariable(macro.getValueType()) || size(macro.getStringListValue()) < 2)){ String ref = getMacroReference(macro); if(ref != null) resolved = new ResolvedMacro(macro.getName(),ref); } if(resolved != null) return resolved; return super.resolveMacro(macro); } private static int size(String[] value){ return value != null ? value.length : 0; } public IConfiguration getConfiguration(){ return fConfiguration; } protected IReservedMacroNameSupplier getReservedMacroNameSupplier(){ if(fBuilder == null) return null; IReservedMacroNameSupplier supplier = fBuilder.getReservedMacroNameSupplier(); if(supplier == null) supplier = new DefaultReservedMacroNameSupplier(fConfiguration); return supplier; } protected String getMacroReference(ICdtVariable macro){ String macroName = macro.getName(); String ref = null; IReservedMacroNameSupplier supplier = getReservedMacroNameSupplier(); //on win32 all environment variable names are converted to upper case macroName = EnvVarOperationProcessor.normalizeName(macroName); if(supplier == null || !supplier.isReservedName(macroName,fConfiguration)){ String pattern = fBuilder.getBuilderVariablePattern(); if(pattern != null && pattern.indexOf(PATTERN_MACRO_NAME) != -1){ if(fBuilder.isVariableCaseSensitive() || getCaseInsensitiveReferencedNames().add(macroName.toUpperCase())){ ref = pattern.replaceAll(PATTERN_MACRO_NAME,macroName); } } } return ref; } protected Set<String> getCaseInsensitiveReferencedNames(){ if(fCaseInsensitiveReferencedNames == null) fCaseInsensitiveReferencedNames = new HashSet<String>(); return fCaseInsensitiveReferencedNames; } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.internal.macros.DefaultMacroSubstitutor#setMacroContextInfo(org.eclipse.cdt.managedbuilder.internal.macros.IMacroContextInfo) */ @Override public void setMacroContextInfo(IVariableContextInfo info) throws CdtVariableException{ super.setMacroContextInfo(info); if(info instanceof IMacroContextInfo) init(null, (IMacroContextInfo)info); } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.internal.macros.IMacroSubstitutor#setMacroContextInfo(int, java.lang.Object) */ // public void setMacroContextInfo(int contextType, Object contextData) throws BuildMacroException{ // super.setMacroContextInfo(contextType, contextData); // init(); // } }