/******************************************************************************* * Copyright (c) 2004, 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 - Initial API and implementation * Martin Oberhuber (Wind River Systems) - bug 155096 * Gerhard Schaber (Wind River Systems) * Markus Schorn (Wind River Systems) * Martin Oberhuber (Wind River) - bug 345750: discover drive-relative paths *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.cdt.core.IMarkerGenerator; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CCommandDSC; import org.eclipse.cdt.make.internal.core.scannerconfig.util.KVStringPair; import org.eclipse.cdt.make.internal.core.scannerconfig.util.SCDOptionsEnum; import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; /** * TODO Provide description * * @author vhirsl */ public class GCCPerFileBOPConsoleParserUtility extends AbstractGCCBOPConsoleParserUtility { private Map<String, List<Map<String, List<String>>>> directoryCommandListMap; private List<String> compiledFileList; private List<CCommandDSC> commandsList2; private int workingDirsN = 0; private int commandsN = 0; private int filesN = 0; private String fDefaultMacroDefinitionValue= "1"; //$NON-NLS-1$ public GCCPerFileBOPConsoleParserUtility(IProject project, IPath workingDirectory, IMarkerGenerator markerGenerator) { super(project, workingDirectory, markerGenerator); } void addGenericCommandForFile(String longFileName, String genericCommand) { // if a file name has already been added once, return if (compiledFileList.contains(longFileName)) return; compiledFileList.add(longFileName); String workingDir = getWorkingDirectory().toString(); List<Map<String, List<String>>> directoryCommandList = directoryCommandListMap.get(workingDir); if (directoryCommandList == null) { directoryCommandList = new CopyOnWriteArrayList<Map<String, List<String>>>(); directoryCommandListMap.put(workingDir, directoryCommandList); ++workingDirsN; } Map<String, List<String>> command21FileListMap = null; for (Map<String, List<String>> map : directoryCommandList) { command21FileListMap = map; List<String> fileList = command21FileListMap.get(genericCommand); if (fileList != null) { if (!fileList.contains(longFileName)) { fileList.add(longFileName); ++filesN; } return; } } command21FileListMap = new HashMap<String, List<String>>(1); directoryCommandList.add(command21FileListMap); ++commandsN; List<String> fileList = new CopyOnWriteArrayList<String>(); command21FileListMap.put(genericCommand, fileList); fileList.add(longFileName); ++filesN; } /** * */ void generateReport() { TraceUtil.metricsTrace("Stats for directory ", //$NON-NLS-1$ "Generic command: '", "' applicable for:", //$NON-NLS-1$ //$NON-NLS-2$ directoryCommandListMap); TraceUtil.summaryTrace("Discovery summary", workingDirsN, commandsN, filesN); //$NON-NLS-1$ } /** * Adds a mapping command line -> file, this time without a dir */ void addGenericCommandForFile2(String longFileName, String genericLine) { // if a file name has already been added once, return if (compiledFileList.contains(longFileName)) return; compiledFileList.add(longFileName); String[] tokens = genericLine.split("\\s+"); //$NON-NLS-1$ CCommandDSC command = getNewCCommandDSC(tokens, 0, false); // assume .c file type int index = commandsList2.indexOf(command); if (index == -1) { commandsList2.add(command); ++commandsN; } else { command = commandsList2.get(index); } // // add a file // command.addFile(longFileName); // ++filesN; } /** * @return CCommandDSC compile command description */ public CCommandDSC getNewCCommandDSC(String[] tokens, final int idxOfCompilerCommand, boolean cppFileType) { CopyOnWriteArrayList<KVStringPair> dirafter = new CopyOnWriteArrayList<KVStringPair>(); CopyOnWriteArrayList<String> includes = new CopyOnWriteArrayList<String>(); CCommandDSC command = new CCommandDSC(cppFileType, getProject()); command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), tokens[idxOfCompilerCommand])); for (int i = idxOfCompilerCommand+1; i < tokens.length; ++i) { String token = tokens[i]; //Target specific options: see GccScannerInfoConsoleParser if (token.startsWith("-m") || //$NON-NLS-1$ token.startsWith("--sysroot") || //$NON-NLS-1$ token.equals("-ansi") || //$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$ ) { command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), token)); continue; } for (int j = SCDOptionsEnum.MIN; j <= SCDOptionsEnum.MAX; ++j) { final SCDOptionsEnum optionKind = SCDOptionsEnum.getSCDOptionsEnum(j); if (token.startsWith(optionKind.toString())) { String option = token.substring( optionKind.toString().length()).trim(); if (option.length() > 0) { // ex. -I/dir } else if (optionKind.equals(SCDOptionsEnum.IDASH)) { for (String inc : includes) { option = inc; KVStringPair pair = new KVStringPair(SCDOptionsEnum.IQUOTE.toString(), option); command.addSCOption(pair); } includes = new CopyOnWriteArrayList<String>(); // -I- has no parameter } else { // ex. -I /dir // take a next token if (i+1 < tokens.length && !tokens[i+1].startsWith("-")) { //$NON-NLS-1$ option = tokens[++i]; } else break; } if (option.length() > 0 && ( optionKind.equals(SCDOptionsEnum.INCLUDE) || optionKind.equals(SCDOptionsEnum.INCLUDE_FILE) || optionKind.equals(SCDOptionsEnum.IMACROS_FILE) || optionKind.equals(SCDOptionsEnum.IDIRAFTER) || optionKind.equals(SCDOptionsEnum.ISYSTEM) || optionKind.equals(SCDOptionsEnum.IQUOTE) )) { option = (getAbsolutePath(option)).toString(); } if (optionKind.equals(SCDOptionsEnum.IDIRAFTER)) { KVStringPair pair = new KVStringPair(SCDOptionsEnum.INCLUDE.toString(), option); dirafter.add(pair); } else if (optionKind.equals(SCDOptionsEnum.INCLUDE)) { includes.add(option); } else { // add the pair if (optionKind.equals(SCDOptionsEnum.DEFINE)) { if (option.indexOf('=') == -1) { option += '='+ fDefaultMacroDefinitionValue; } } KVStringPair pair = new KVStringPair(optionKind.toString(), option); command.addSCOption(pair); } break; } } } for (String option : includes) { KVStringPair pair = new KVStringPair(SCDOptionsEnum.INCLUDE.toString(), option); command.addSCOption(pair); } for (KVStringPair kvStringPair : dirafter) { command.addSCOption(kvStringPair); } return command; } public void setDefaultMacroDefinitionValue(String val) { if (val != null) { fDefaultMacroDefinitionValue= val; } } /** * @param filePath : String * @return filePath : IPath - not <code>null</code> */ public IPath getAbsolutePath(String filePath) { IPath pFilePath; if (filePath.startsWith("/")) { //$NON-NLS-1$ pFilePath = convertCygpath(new Path(filePath)); } else if (filePath.startsWith("\\") || //$NON-NLS-1$ (!filePath.startsWith(".") && //$NON-NLS-1$ filePath.length() > 2 && filePath.charAt(1) == ':' && (filePath.charAt(2) == '\\' || filePath.charAt(2) == '/'))) { // absolute path pFilePath = new Path(filePath); } else { // relative path IPath cwd = getWorkingDirectory(); if (!cwd.isAbsolute()) { cwd = getBaseDirectory().append(cwd); } if (filePath.startsWith("`pwd`")) { //$NON-NLS-1$ if (filePath.length() > 5 && (filePath.charAt(5) == '/' || filePath.charAt(5) == '\\')) { filePath = filePath.substring(6); } else { filePath = filePath.substring(5); } } pFilePath = cwd.append(filePath); } if (pFilePath.getDevice()==null) { pFilePath = pFilePath.setDevice(getWorkingDirectory().getDevice()); } return pFilePath; } /** * */ // void generateReport2() { // StringWriter buffer = new StringWriter(); // PrintWriter writer = new PrintWriter(buffer); // for (Iterator i = commandsList2.iterator(); i.hasNext(); ) { // CCommandDSC cmd = (CCommandDSC)i.next(); // writer.println("Stats for generic command: '" + cmd.getCommandAsString() + "' applicable for " + // Integer.toString(cmd.getNumberOfFiles()) + " files: "); // List filesList = cmd.getFilesList(); // if (filesList != null) { // for (Iterator j = filesList.iterator(); j.hasNext(); ) { // writer.println(" " + (String)j.next()); // } // } // } // writer.close(); // // TraceUtil.metricsTrace(buffer.toString()); // TraceUtil.summaryTrace("Discovery summary", workingDirsN, commandsN, filesN); // } /** * Returns all CCommandDSC collected so far. * Currently this list is not filled, so it will always return an empty list. * @return List of CCommandDSC */ public List<CCommandDSC> getCCommandDSCList() { return new CopyOnWriteArrayList<CCommandDSC>(commandsList2); } }