/******************************************************************************* * Copyright (c) 2004, 2011 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 - Initial API and implementation * Martin Oberhuber (Wind River Systems) - bug 155096 * Sergey Prigogin (Google) * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; /** * Parses gcc and g++ output for -I and -D parameters. * * @author vhirsl */ public class GCCScannerInfoConsoleParser extends AbstractGCCBOPConsoleParser { protected ScannerInfoConsoleParserUtility fUtil = null; private String fDefaultMacroDefinitionValue= "1"; //$NON-NLS-1$ /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#startup(org.eclipse.core.resources.IProject, org.eclipse.core.runtime.IPath, org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector, org.eclipse.cdt.core.IMarkerGenerator) */ public void startup(IProject project, IPath workingDirectory, IScannerInfoCollector collector, IMarkerGenerator markerGenerator) { fUtil = (project != null && workingDirectory != null && markerGenerator != null) ? new ScannerInfoConsoleParserUtility(project, workingDirectory, markerGenerator) : null; super.startup(project, collector); } /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#getUtility() */ @Override protected AbstractGCCBOPConsoleParserUtility getUtility() { return fUtil; } @Override protected boolean processCommand(String[] tokens) { int compilerInvocationIdx= findCompilerInvocation(tokens); if (compilerInvocationIdx<0) { return false; } if (compilerInvocationIdx+1 >= tokens.length) { return false; } // Recognized gcc or g++ compiler invocation List<String> includes = new ArrayList<String>(); List<String> symbols = new ArrayList<String>(); List<String> targetSpecificOptions = new ArrayList<String>(); String fileName = null; for (int j= compilerInvocationIdx+1; j < tokens.length; j++) { String token = tokens[j]; if (token.equals(DASHIDASH)) { } else if (token.startsWith(DASHI)) { String candidate= null; if (token.length() > 2) { candidate= token.substring(2).trim(); } else if (j+1 < tokens.length) { candidate= tokens[j+1]; if (candidate.startsWith("-")) { //$NON-NLS-1$ candidate= null; } else { j++; } } if (candidate != null && candidate.length() > 0) { if (fUtil != null) { candidate= fUtil.normalizePath(candidate); } if (!includes.contains(candidate)) { includes.add(candidate); } } } else if (token.startsWith(DASHD)) { String candidate= null; if (token.length() > 2) { candidate= token.substring(2).trim(); } else if (j+1 < tokens.length) { candidate= tokens[j+1]; if (candidate.startsWith("-")) { //$NON-NLS-1$ candidate= null; } else { j++; } } if (candidate != null && candidate.length() > 0) { if (candidate.indexOf('=') == -1) { candidate+= '='+ fDefaultMacroDefinitionValue; } if (!symbols.contains(candidate)) { symbols.add(candidate); } } } else if (token.startsWith("-m") || //$NON-NLS-1$ token.startsWith("--sysroot") || //$NON-NLS-1$ token.equals("-ansi") || //$NON-NLS-1$ token.equals("-nostdinc") || //$NON-NLS-1$ token.equals("-posix") || //$NON-NLS-1$ token.equals("-pthread") || //$NON-NLS-1$ token.startsWith("-O") || //$NON-NLS-1$ token.equals("-fno-inline") || //$NON-NLS-1$ token.startsWith("-finline") || //$NON-NLS-1$ token.equals("-fno-exceptions") || //$NON-NLS-1$ token.equals("-fexceptions") || //$NON-NLS-1$ token.equals("-fshort-wchar") || //$NON-NLS-1$ token.equals("-fshort-double") || //$NON-NLS-1$ token.equals("-fno-signed-char") || //$NON-NLS-1$ token.equals("-fsigned-char") || //$NON-NLS-1$ token.startsWith("-fabi-version=")) { //$NON-NLS-1$ if (!targetSpecificOptions.contains(token)) targetSpecificOptions.add(token); } else if (fileName == null) { String possibleFileName = token.toLowerCase(); if (possibleFileName.endsWith(".c") || //$NON-NLS-1$ possibleFileName.endsWith(".cpp") || //$NON-NLS-1$ possibleFileName.endsWith(".cc") || //$NON-NLS-1$ possibleFileName.endsWith(".cxx") || //$NON-NLS-1$ possibleFileName.endsWith(".C") || //$NON-NLS-1$ possibleFileName.endsWith(".CPP") || //$NON-NLS-1$ possibleFileName.endsWith(".CC") || //$NON-NLS-1$ possibleFileName.endsWith(".CXX") || //$NON-NLS-1$ possibleFileName.endsWith(".c++")) { //$NON-NLS-1$ fileName = token; } } } if (fileName != null && fileName.startsWith("/cygdrive/")) { //$NON-NLS-1$ fileName= AbstractGCCBOPConsoleParserUtility.convertCygpath(new Path(fileName)).toOSString(); } if (fileName == null || fileName.trim().length()==0) { return false; // return when no file was given (analogous to GCCPerFileBOPConsoleParser) } IProject project = getProject(); IFile file = null; List<String> translatedIncludes = includes; if (includes.size() > 0) { if (fUtil != null) { file = fUtil.findFile(fileName); if (file != null) { project = file.getProject(); translatedIncludes = fUtil.translateRelativePaths(file, fileName, includes); } } if (file == null && fUtil != null) { // real world case // remove non-absolute include paths since there was no chance to translate them Iterator<String> iterator = translatedIncludes.iterator(); while (iterator.hasNext()) { String include = iterator.next(); IPath includePath = new Path(include); if (!includePath.isAbsolute() && !includePath.isUNC()) { // do not translate UNC paths iterator.remove(); } } } } // Contribute discovered includes and symbols to the ScannerInfoCollector if (translatedIncludes.size() > 0 || symbols.size() > 0) { Map<ScannerInfoTypes, List<String>> scannerInfo = new HashMap<ScannerInfoTypes, List<String>>(); scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, translatedIncludes); scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); scannerInfo.put(ScannerInfoTypes.TARGET_SPECIFIC_OPTION, targetSpecificOptions); getCollector().contributeToScannerConfig(project, scannerInfo); TraceUtil.outputTrace("Discovered scanner info for file \'" + fileName + '\'', //$NON-NLS-1$ "Include paths", includes, translatedIncludes, "Defined symbols", symbols); //$NON-NLS-1$ //$NON-NLS-2$ } return true; } public void setDefaultMacroDefinitionValue(String val) { if (val != null) { fDefaultMacroDefinitionValue= val; } } }