/******************************************************************************* * Copyright (c) 2009, 2013 Andrew Gvozdev 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: * Andrew Gvozdev - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.language.settings.providers; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider; import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.core.runtime.CoreException; /** * Language settings provider to detect built-in compiler settings for GCC compiler. * <p> * <strong>EXPERIMENTAL</strong>. This class interface is not stable yet as * it is not currently (CDT 8.1, Juno) clear how it may need to be used in future. * There is no guarantee that this API will work or that it will remain the same. * Please do not use this API without consulting with the CDT team. * </p> * @noextend This class is not intended to be subclassed by clients. * * @since 8.1 */ public class GCCBuiltinSpecsDetector extends ToolchainBuiltinSpecsDetector implements ILanguageSettingsEditableProvider { // ID must match the tool-chain definition in org.eclipse.cdt.managedbuilder.core.buildDefinitions extension point private static final String GCC_TOOLCHAIN_ID = "cdt.managedbuild.toolchain.gnu.base"; //$NON-NLS-1$ private enum State {NONE, EXPECTING_LOCAL_INCLUDE, EXPECTING_SYSTEM_INCLUDE, EXPECTING_FRAMEWORKS} private State state = State.NONE; @SuppressWarnings("nls") private static final AbstractOptionParser[] optionParsers = { new IncludePathOptionParser("#include \"(\\S.*)\"", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.LOCAL), new IncludePathOptionParser("#include <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), new IncludePathOptionParser("#framework <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.FRAMEWORKS_MAC), new MacroOptionParser("#define\\s+(\\S*\\(.*?\\))\\s*(.*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), new MacroOptionParser("#define\\s+(\\S*)\\s*(.*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), }; /** * @since 8.2 */ @Override public String getToolchainId() { return GCC_TOOLCHAIN_ID; } @Override protected AbstractOptionParser[] getOptionParsers() { return optionParsers; } /** * Create a list from one item. */ private List<String> makeList(String line) { List<String> list = new ArrayList<String>(); list.add(line); return list; } @SuppressWarnings("nls") @Override protected List<String> parseOptions(String line) { line = line.trim(); // contribution of -dD option if (line.startsWith("#define")) { return makeList(line); } // contribution of includes if (line.equals("#include \"...\" search starts here:")) { state = State.EXPECTING_LOCAL_INCLUDE; } else if (line.equals("#include <...> search starts here:")) { state = State.EXPECTING_SYSTEM_INCLUDE; } else if (line.startsWith("End of search list.")) { state = State.NONE; } else if (line.equals("Framework search starts here:")) { state = State.EXPECTING_FRAMEWORKS; } else if (line.startsWith("End of framework search list.")) { state = State.NONE; } else if (state==State.EXPECTING_LOCAL_INCLUDE) { // making that up for the parser to figure out line = "#include \""+line+"\""; return makeList(line); } else { String frameworkIndicator = "(framework directory)"; if (state==State.EXPECTING_SYSTEM_INCLUDE) { // making that up for the parser to figure out if (line.contains(frameworkIndicator)) { line = "#framework <"+line.replace(frameworkIndicator, "").trim()+">"; } else { line = "#include <"+line+">"; } return makeList(line); } else if (state==State.EXPECTING_FRAMEWORKS) { // making that up for the parser to figure out line = "#framework <"+line.replace(frameworkIndicator, "").trim()+">"; return makeList(line); } } return null; } @Override public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException { super.startup(cfgDescription, cwdTracker); state = State.NONE; } @Override public void shutdown() { state = State.NONE; super.shutdown(); } @Override public GCCBuiltinSpecsDetector cloneShallow() throws CloneNotSupportedException { return (GCCBuiltinSpecsDetector) super.cloneShallow(); } @Override public GCCBuiltinSpecsDetector clone() throws CloneNotSupportedException { return (GCCBuiltinSpecsDetector) super.clone(); } }