diff options
author | Mikhail Sennikovsky | 2007-03-06 18:48:55 +0000 |
---|---|---|
committer | Mikhail Sennikovsky | 2007-03-06 18:48:55 +0000 |
commit | 6524989ba78457a202af744c22008c53ccad4e9f (patch) | |
tree | 922dfe896b75ab331dc66fecbb37a265cb302a1a /build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig | |
parent | 99affdf6462618d31cea71ef9fc79d145f84db0f (diff) | |
download | org.eclipse.cdt-6524989ba78457a202af744c22008c53ccad4e9f.tar.gz org.eclipse.cdt-6524989ba78457a202af744c22008c53ccad4e9f.tar.xz org.eclipse.cdt-6524989ba78457a202af744c22008c53ccad4e9f.zip |
1. Build System Backward Compatibility
Diffstat (limited to 'build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig')
28 files changed, 5305 insertions, 0 deletions
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathContainer.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathContainer.java new file mode 100644 index 00000000000..d952523e24d --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathContainer.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.model.IPathEntryContainer; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +public class DiscoveredPathContainer implements IPathEntryContainer { + public static final IPath CONTAINER_ID = new Path("org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"); //$NON-NLS-1$ + + protected final IProject fProject; + private IPathEntry[] fPathEntries; + + public DiscoveredPathContainer(IProject project) { + fProject = project; + fPathEntries = null; + } + +// public IPathEntry[] getPathEntries() { +// IPathEntry[] fPathEntries; +// try { +// fPathEntries = getPathEntries(getPathEntryMap()); +// } catch (CoreException e) { +// MakeCorePlugin.log(e); +// return new IPathEntry[0]; +// } +// return fPathEntries; +// } + + public String getDescription() { + return MakeMessages.getString("DiscoveredContainer.description"); //$NON-NLS-1$ + } + + public IPath getPath() { + return CONTAINER_ID; + } + + public IPathEntry[] getPathEntries() { + if (fPathEntries == null) { + try { + fPathEntries = computeNewPathEntries(); + } + catch (CoreException e) { + MakeCorePlugin.log(e); + return new IPathEntry[0]; + } + } + return fPathEntries; + } + + private IPathEntry[] computeNewPathEntries() throws CoreException { + IDiscoveredPathInfo info = MakeCorePlugin.getDefault().getDiscoveryManager().getDiscoveredInfo(fProject); + IPath[] includes = info.getIncludePaths(); + Map syms = info.getSymbols(); + List entries = new ArrayList(includes.length + syms.size()); + for (int i = 0; i < includes.length; i++) { + entries.add(CoreModel.newIncludeEntry(Path.EMPTY, Path.EMPTY, includes[i], true)); //$NON-NLS-1$ //$NON-NLS-2$ + } + Iterator iter = syms.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = (Entry)iter.next(); + entries.add(CoreModel.newMacroEntry(Path.EMPTY, (String)entry.getKey(), (String)entry.getValue())); //$NON-NLS-1$ + } + return (IPathEntry[])entries.toArray(new IPathEntry[entries.size()]); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInfo.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInfo.java new file mode 100644 index 00000000000..cecddaa0b95 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInfo.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredScannerInfoSerializable; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerProjectDiscoveredPathInfo; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.SymbolEntry; +import org.eclipse.cdt.make.internal.core.scannerconfig2.PerProjectSICollector; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +public class DiscoveredPathInfo implements IPerProjectDiscoveredPathInfo, IDiscoveredScannerInfoSerializable { + public static final String INCLUDE_PATH = "includePath"; //$NON-NLS-1$ + public static final String PATH = "path"; //$NON-NLS-1$ + public static final String DEFINED_SYMBOL = "definedSymbol"; //$NON-NLS-1$ + public static final String SYMBOL = "symbol"; //$NON-NLS-1$ + public static final String REMOVED = "removed"; //$NON-NLS-1$ + + final private IProject project; + private LinkedHashMap discoveredPaths; + private LinkedHashMap discoveredSymbols; + + private List activePaths; + private Map activeSymbols; + + public DiscoveredPathInfo(IProject project) { + this.project = project; + discoveredPaths = new LinkedHashMap(); + discoveredSymbols = new LinkedHashMap(); + } + + public IProject getProject() { + return project; + } + + public synchronized Map getSymbols() { + if (activeSymbols == null) { + createSymbolsMap(); + } + Map dSymbols = ScannerConfigUtil.scSymbolEntryMap2Map(discoveredSymbols); + return dSymbols; + } + + public synchronized IPath[] getIncludePaths() { + if ( activePaths == null) { + createPathLists(); + } + return (IPath[])activePaths.toArray(new IPath[activePaths.size()]); + } + + public LinkedHashMap getIncludeMap() { + return new LinkedHashMap(discoveredPaths); + } + + public synchronized void setIncludeMap(LinkedHashMap paths) { + discoveredPaths = new LinkedHashMap(paths); + activePaths = null; + } + + /** + * Populates active and removed include path lists + */ + private void createPathLists() { + List aPaths = getActivePathList(); + aPaths.clear(); + + for (Iterator i = discoveredPaths.keySet().iterator(); i.hasNext(); ) { + String path = (String) i.next(); + Boolean removed = (Boolean) discoveredPaths.get(path); + if (removed == null || removed.booleanValue() == false) { + aPaths.add(new Path(path)); + } + } + } + + public LinkedHashMap getSymbolMap() { + return new LinkedHashMap(discoveredSymbols); + } + + public synchronized void setSymbolMap(LinkedHashMap symbols) { + discoveredSymbols = new LinkedHashMap(symbols); + activeSymbols = null; + } + + /** + * Populates active symbols sets + */ + private void createSymbolsMap() { + Map aSymbols = getActiveSymbolsMap(); + aSymbols.clear(); + + aSymbols.putAll(ScannerConfigUtil.scSymbolEntryMap2Map(discoveredSymbols)); + } + + private List getActivePathList() { + if (activePaths == null) { + activePaths = new ArrayList(); + } + return activePaths; + } + + private Map getActiveSymbolsMap() { + if (activeSymbols == null) { + activeSymbols = new HashMap(); + } + return activeSymbols; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#serialize(org.w3c.dom.Element) + */ + public void serialize(Element collectorElem) { + Document doc = collectorElem.getOwnerDocument(); + + Map includes = getIncludeMap(); + Iterator iter = includes.keySet().iterator(); + while (iter.hasNext()) { + Element pathElement = doc.createElement(INCLUDE_PATH); + String include = (String)iter.next(); + pathElement.setAttribute(PATH, include); + Boolean removed = (Boolean)includes.get(include); + if (removed != null && removed.booleanValue() == true) { + pathElement.setAttribute(REMOVED, "true"); //$NON-NLS-1$ + } + collectorElem.appendChild(pathElement); + } + // Now do the same for the symbols + Map symbols = getSymbolMap(); + iter = symbols.keySet().iterator(); + while (iter.hasNext()) { + String symbol = (String)iter.next(); + SymbolEntry se = (SymbolEntry)symbols.get(symbol); + for (Iterator i = se.getActiveRaw().iterator(); i.hasNext();) { + String value = (String)i.next(); + Element symbolElement = doc.createElement(DEFINED_SYMBOL); + symbolElement.setAttribute(SYMBOL, value); + collectorElem.appendChild(symbolElement); + } + for (Iterator i = se.getRemovedRaw().iterator(); i.hasNext();) { + String value = (String)i.next(); + Element symbolElement = doc.createElement(DEFINED_SYMBOL); + symbolElement.setAttribute(SYMBOL, value); + symbolElement.setAttribute(REMOVED, "true"); //$NON-NLS-1$ + collectorElem.appendChild(symbolElement); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#deserialize(org.w3c.dom.Element) + */ + public void deserialize(Element collectorElem) { + LinkedHashMap includes = getIncludeMap(); + LinkedHashMap symbols = getSymbolMap(); + + Node child = collectorElem.getFirstChild(); + while (child != null) { + if (child.getNodeName().equals(INCLUDE_PATH)) { + // Add the path to the property list + includes.put( ((Element)child).getAttribute(PATH), Boolean.valueOf( ((Element)child).getAttribute(REMOVED))); + } else if (child.getNodeName().equals(DEFINED_SYMBOL)) { + // Add the symbol to the symbol list + String symbol = ((Element)child).getAttribute(SYMBOL); + String removed = ((Element)child).getAttribute(REMOVED); + boolean bRemoved = (removed != null && removed.equals("true")); //$NON-NLS-1$ + ScannerConfigUtil.scAddSymbolString2SymbolEntryMap(symbols, symbol, !bRemoved); + } + child = child.getNextSibling(); + } + + setIncludeMap(includes); + setSymbolMap(symbols); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#getCollectorId() + */ + public String getCollectorId() { + return PerProjectSICollector.COLLECTOR_ID; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getSerializable() + */ + public IDiscoveredScannerInfoSerializable getSerializable() { + return this; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInitializer.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInitializer.java new file mode 100644 index 00000000000..ac3d3ccd4e9 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathInitializer.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.PathEntryContainerInitializer; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; +import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigScope; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + + +public class DiscoveredPathInitializer extends PathEntryContainerInitializer { + + public void initialize(IPath containerPath, ICProject cProject) throws CoreException { + IProject project = cProject.getProject(); + IScannerConfigBuilderInfo2 buildInfo = ScannerConfigProfileManager.createScannerConfigBuildInfo2(project); + ScannerConfigScope profileScope = ScannerConfigProfileManager.getInstance(). + getSCProfileConfiguration(buildInfo.getSelectedProfileId()).getProfileScope(); + if (ScannerConfigScope.PROJECT_SCOPE.equals(profileScope)) { + CoreModel.setPathEntryContainer(new ICProject[]{cProject}, new DiscoveredPathContainer(project), null); + } + else if (ScannerConfigScope.FILE_SCOPE.equals(profileScope)) { + CoreModel.setPathEntryContainer(new ICProject[]{cProject}, new PerFileDiscoveredPathContainer(project), null); + } + else { + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), 1, + MakeMessages.getString("DiscoveredContainer.ScopeErrorMessage"), null)); //$NON-NLS-1$ + } + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathManager.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathManager.java new file mode 100644 index 00000000000..755c1c07227 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredPathManager.java @@ -0,0 +1,354 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 QNX Software Systems 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: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.PathEntryContainerChanged; +import org.eclipse.cdt.core.settings.model.util.PathSettingsContainer; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2Set; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigScope; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig2.SCProfileInstance; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; + + +public class DiscoveredPathManager implements IDiscoveredPathManager, IResourceChangeListener { + + private Map fDiscoveredInfoHolderMap = new HashMap(); + private List listeners = Collections.synchronizedList(new ArrayList()); + + private static final int INFO_CHANGED = 1; + private static final int INFO_REMOVED = 2; + + private static class DiscoveredInfoHolder { + Map fInfoMap = new HashMap(); +// PathSettingsContainer fContainer = PathSettingsContainer.createRootContainer(); + + public IDiscoveredPathInfo getInfo(InfoContext context){ + return (IDiscoveredPathInfo)fInfoMap.get(context); + } + +// private Map getMap(IPath path, boolean create, boolean exactPath){ +// PathSettingsContainer child = fContainer.getChildContainer(path, create, exactPath); +// Map map = null; +// if(child != null){ +// map = (Map)child.getValue(); +// if(map == null && create){ +// map = new HashMap(); +// child.setValue(map); +// } +// } +// +// return map; +// } + +// public IDiscoveredPathInfo getInfo(IFile file, String instanceId){ +// IPath path = file.getProjectRelativePath(); +// Map map = getMap(path, false, false); +// for(Iterator iter = map.entrySet().iterator(); iter.hasNext();){ +// Map.Entry entry = (Map.Entry)iter.next(); +// InfoContext context = (InfoContext)entry.getKey(); +// if(context.matches(file)) +// return (IDiscoveredPathInfo)entry.getValue(); +// } +// return null; +// } + + public IDiscoveredPathInfo setInfo(InfoContext context, IDiscoveredPathInfo info){ + if(info != null) + return (IDiscoveredPathInfo)fInfoMap.put(context, info); + return (IDiscoveredPathInfo)fInfoMap.remove(context); + } + + } + + public DiscoveredPathManager() { + + } + + public void startup() { + ResourcesPlugin.getWorkspace().addResourceChangeListener(this); + } + + public void shutdown() { + ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) + */ + public void resourceChanged(IResourceChangeEvent event) { + if (event.getSource() instanceof IWorkspace) { + IResource resource = event.getResource(); + + switch (event.getType()) { + case IResourceChangeEvent.POST_CHANGE : + DiscoveredScannerInfoStore.getInstance().updateScannerConfigStore(event.getDelta()); + break; + case IResourceChangeEvent.PRE_DELETE : + case IResourceChangeEvent.PRE_CLOSE : + if (resource.getType() == IResource.PROJECT) { + //TODO: better handlind of resource remove/rename + fDiscoveredInfoHolderMap.remove(resource); + } + break; + } + } + } + + + + public IDiscoveredPathInfo getDiscoveredInfo(IProject project) throws CoreException { + return getDiscoveredInfo(project, new InfoContext(project)); + } + + public IDiscoveredPathInfo getDiscoveredInfo(IProject project, InfoContext context) throws CoreException{ + DiscoveredInfoHolder holder = getHolder(project, true); + IDiscoveredPathInfo info = holder.getInfo(context); + + if(info == null){ + info = loadPathInfo(project, context); + holder.setInfo(context, info); + } + + return info; + } + + private DiscoveredInfoHolder getHolder(IProject project, boolean create){ + DiscoveredInfoHolder holder = (DiscoveredInfoHolder)fDiscoveredInfoHolderMap.get(project); + if(holder == null && create){ + holder = new DiscoveredInfoHolder(); + fDiscoveredInfoHolderMap.put(project, holder); + } + return holder; + } + + private IDiscoveredPathInfo loadPathInfo(IProject project, InfoContext context) throws CoreException { + IDiscoveredPathInfo pathInfo = null; + + IScannerConfigBuilderInfo2Set container = ScannerConfigProfileManager.createScannerConfigBuildInfo2Set(project); + IScannerConfigBuilderInfo2 buildInfo = container.getInfo(context); + if(buildInfo != null){ + String profileId = buildInfo.getSelectedProfileId(); + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(project, context, profileId); + IScannerInfoCollector collector = profileInstance.getScannerInfoCollector(); + + if (collector instanceof IScannerInfoCollector2) { + IScannerInfoCollector2 collector2 = (IScannerInfoCollector2) collector; + pathInfo = collector2.createPathInfoObject(); + } + } + if(pathInfo == null) { + pathInfo = new DiscoveredPathInfo(project); + } + return pathInfo; + } + + + + +// private DiscoveredInfoHolder getHolder + +// private IDiscoveredPathInfo loadPathInfo(IProject project) throws CoreException { +// IDiscoveredPathInfo pathInfo = null; +// +// IScannerConfigBuilderInfo2 buildInfo = ScannerConfigProfileManager.createScannerConfigBuildInfo2(project); +// String profileId = buildInfo.getSelectedProfileId(); +// SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). +// getSCProfileInstance(project, profileId); +// IScannerInfoCollector collector = profileInstance.getScannerInfoCollector(); +// +// if (collector instanceof IScannerInfoCollector2) { +// IScannerInfoCollector2 collector2 = (IScannerInfoCollector2) collector; +// pathInfo = collector2.createPathInfoObject(); +// } +// else { +// pathInfo = new DiscoveredPathInfo(project); +// } +// return pathInfo; +// } + + public void removeDiscoveredInfo(IProject project) { + removeDiscoveredInfo(project, new InfoContext(project)); + } + + public void removeDiscoveredInfo(IProject project, InfoContext context) { + DiscoveredInfoHolder holder = getHolder(project, false); + if(holder != null){ + IDiscoveredPathInfo info = holder.setInfo(context, null); + if (info != null) { + fireUpdate(INFO_REMOVED, info); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager#updateDiscoveredInfo(org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo, java.util.List) + */ + public void updateDiscoveredInfo(IDiscoveredPathInfo info, List changedResources) throws CoreException { + updateDiscoveredInfo(new InfoContext(info.getProject()), info, true, changedResources); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager#updateDiscoveredInfo(org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo, java.util.List) + */ + public void updateDiscoveredInfo(InfoContext context, IDiscoveredPathInfo info, boolean updateContainer, List changedResources) throws CoreException { + DiscoveredInfoHolder holder = getHolder(info.getProject(), false); + if (holder != null && holder.getInfo(context) != null) { + IDiscoveredScannerInfoSerializable serializable = info.getSerializable(); + if (serializable != null) { + IProject project = info.getProject(); + DiscoveredScannerInfoStore.getInstance().saveDiscoveredScannerInfoToState(project, context, serializable); + fireUpdate(INFO_CHANGED, info); + + if(updateContainer){ +// ICProject cProject = CoreModel.getDefault().create(info.getProject()); +// if (cProject != null) { +// CoreModel.setPathEntryContainer(new ICProject[]{cProject}, +// new DiscoveredPathContainer(info.getProject()), null); +// } + IScannerConfigBuilderInfo2 buildInfo = ScannerConfigProfileManager.createScannerConfigBuildInfo2(project); + String profileId = buildInfo.getSelectedProfileId(); + ScannerConfigScope profileScope = ScannerConfigProfileManager.getInstance(). + getSCProfileConfiguration(profileId).getProfileScope(); + changeDiscoveredContainer(project, profileScope, changedResources); + } + } + else { + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.Info_Not_Serializable"), null)); //$NON-NLS-1$ + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager#changeDiscoveredContainer(org.eclipse.core.resources.IProject, java.lang.String) + */ + public void changeDiscoveredContainer(final IProject project, final ScannerConfigScope profileScope, final List changedResources) { + // order here is of essence + // 1. clear DiscoveredPathManager's path info cache + DiscoveredInfoHolder holder = getHolder(project, false); + InfoContext context = new InfoContext(project); + IDiscoveredPathInfo oldInfo = (IDiscoveredPathInfo) holder.getInfo(context); + + // 2. switch the containers + try { + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + ICProject cProject = CoreModel.getDefault().create(project); + if (ScannerConfigScope.PROJECT_SCOPE.equals(profileScope)) { + CoreModel.setPathEntryContainer(new ICProject[]{cProject}, + new DiscoveredPathContainer(project), null); + } + else if (ScannerConfigScope.FILE_SCOPE.equals(profileScope)) { + PerFileDiscoveredPathContainer container = new PerFileDiscoveredPathContainer(project); + CoreModel.setPathEntryContainer(new ICProject[]{cProject}, + container, null); + if (changedResources != null) { + List changeDelta = new ArrayList(changedResources.size()); + for (Iterator i = changedResources.iterator(); i.hasNext(); ) { + IResource resource = (IResource) i.next(); + IPath path = resource.getFullPath(); + changeDelta.add(new PathEntryContainerChanged(path, + PathEntryContainerChanged.INCLUDE_CHANGED | + PathEntryContainerChanged.MACRO_CHANGED)); // both include paths and symbols changed + } + CoreModel.pathEntryContainerUpdates(container, + (PathEntryContainerChanged[]) changeDelta.toArray(new PathEntryContainerChanged[changeDelta.size()]), + null); + } + } + else { + MakeCorePlugin.log(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), 1, + MakeMessages.getString("DiscoveredContainer.ScopeErrorMessage"), null)); //$NON-NLS-1$ + } + + } + }; + CoreModel.run(runnable, null); + } + catch (CoreException e) { + MakeCorePlugin.log(e); + } + + // 3. clear the container's path entry cache + if (oldInfo != null) { + fireUpdate(INFO_REMOVED, oldInfo); + } + } + + private void fireUpdate(final int type, final IDiscoveredPathInfo info) { + Object[] list = listeners.toArray(); + for (int i = 0; i < list.length; i++) { + final IDiscoveredInfoListener listener = (IDiscoveredInfoListener)list[i]; + if (listener != null) { + Platform.run(new ISafeRunnable() { + + public void handleException(Throwable exception) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, -1, + CCorePlugin.getResourceString("CDescriptorManager.exception.listenerError"), exception); //$NON-NLS-1$ + CCorePlugin.log(status); + } + + public void run() throws Exception { + switch (type) { + case INFO_CHANGED : + listener.infoChanged(info); + break; + case INFO_REMOVED : + listener.infoRemoved(info); + break; + } + } + }); + } + } + } + + public void addDiscoveredInfoListener(IDiscoveredInfoListener listener) { + listeners.add(listener); + } + + public void removeDiscoveredInfoListener(IDiscoveredInfoListener listener) { + listeners.remove(listener); + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredScannerInfoStore.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredScannerInfoStore.java new file mode 100644 index 00000000000..e27be5792e7 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/DiscoveredScannerInfoStore.java @@ -0,0 +1,437 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredScannerInfoSerializable; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig2.PerProjectSICollector; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Status; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; +import org.xml.sax.SAXException; + +/** + * Discovered scanner info persistance store + * + * @author vhirsl + */ +public class DiscoveredScannerInfoStore { + private static final QualifiedName dscFileNameProperty = new + QualifiedName(MakeCorePlugin.getUniqueIdentifier(), "discoveredScannerConfigFileName"); //$NON-NLS-1$ + private static final String CDESCRIPTOR_ID = MakeCorePlugin.getUniqueIdentifier() + ".discoveredScannerInfo"; //$NON-NLS-1$ + public static final String SCD_STORE_VERSION = "scdStore"; //$NON-NLS-1$ + public static final String SI_ELEM = "scannerInfo"; //$NON-NLS-1$ + public static final String COLLECTOR_ELEM = "collector"; //$NON-NLS-1$ + public static final String ID_ATTR = "id"; //$NON-NLS-1$ + + private static final String INSTANCE_ELEM = "instance"; //$NON-NLS-1$ + + private static DiscoveredScannerInfoStore instance; + + private Map fDocumentMap = new HashMap(); + + public static DiscoveredScannerInfoStore getInstance() { + if (instance == null) { + instance = new DiscoveredScannerInfoStore(); + } + return instance; + } + /** + * + */ + private DiscoveredScannerInfoStore() { + } + + public void loadDiscoveredScannerInfoFromState(IProject project, IDiscoveredScannerInfoSerializable serializable) + throws CoreException { + loadDiscoveredScannerInfoFromState(project, new InfoContext(project), serializable); + } + + public void loadDiscoveredScannerInfoFromState(IProject project, InfoContext context, IDiscoveredScannerInfoSerializable serializable) + throws CoreException { + // Get the document + Element rootElem = getRootElement(project, context, serializable); + + if(rootElem != null){ + // get the collector element + NodeList collectorList = rootElem.getElementsByTagName(COLLECTOR_ELEM); + if (collectorList.getLength() > 0) { + // find the collector element + for (int i = 0; i < collectorList.getLength(); ++i) { + Element collectorElem = (Element) collectorList.item(i); + String collectorId = collectorElem.getAttribute(ID_ATTR); + if (serializable.getCollectorId().equals(collectorId)) { + serializable.deserialize(collectorElem); + break; + } + } + } + } + } + + public boolean hasInfo(IProject project, InfoContext context, IDiscoveredScannerInfoSerializable serializable){ + try { + if(getRootElement(project, context, serializable) != null) + return true; + } catch (CoreException e) { + MakeCorePlugin.log(e); + } + return false; + } + + private Element getRootElement(IProject project, InfoContext context, IDiscoveredScannerInfoSerializable serializable) throws CoreException{ + if(serializable == null) + return null; + + Document document = getDocument(project); + Element rootElem = null; + if (document != null) { + NodeList rootList = document.getElementsByTagName(SI_ELEM); + if (rootList.getLength() > 0) { + rootElem = (Element) rootList.item(0); + + if(!context.isDefaultContext()){ + String instanceId = context.getInstanceId(); + + Element instanceElem = findChild(rootElem, INSTANCE_ELEM, ID_ATTR, instanceId); + + rootElem = instanceElem; + } + } + } + + return rootElem; + } + + private Document getDocument(IProject project) throws CoreException { + // Get the document + Document document = (Document) fDocumentMap.get(project); + if (document == null) { + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + IPath path = getDiscoveredScannerConfigStore(project); + if (path.toFile().exists()) { + // read form file + FileInputStream file = new FileInputStream(path.toFile()); + document = builder.parse(file); + Node rootElem = document.getFirstChild(); + if (rootElem.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE) { + // no version info; upgrade + upgradeDocument(document, project); + } + } + else { + // create new document + document = builder.newDocument(); + ProcessingInstruction pi = document.createProcessingInstruction(SCD_STORE_VERSION, "version=\"2\""); //$NON-NLS-1$ + document.appendChild(pi); + Element rootElement = document.createElement(SI_ELEM); //$NON-NLS-1$ + rootElement.setAttribute(ID_ATTR, CDESCRIPTOR_ID); //$NON-NLS-1$ + document.appendChild(rootElement); + } + fDocumentMap.put(project, document); + } + catch (IOException e) { + MakeCorePlugin.log(e); + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } + catch (ParserConfigurationException e) { + MakeCorePlugin.log(e); + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } + catch (SAXException e) { + MakeCorePlugin.log(e); + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } + } + return document; + } + + /** + * @param document + * @param project + */ + private void upgradeDocument(Document document, IProject project) { + Element rootElem = (Element) document.getElementsByTagName(SI_ELEM).item(0); //$NON-NLS-1$ + ProcessingInstruction pi = document.createProcessingInstruction(SCD_STORE_VERSION, "version=\"2.0\""); //$NON-NLS-1$ + document.insertBefore(pi, rootElem); + + Element collectorElem = document.createElement(COLLECTOR_ELEM); + collectorElem.setAttribute(ID_ATTR, PerProjectSICollector.COLLECTOR_ID); + for (Node child = rootElem.getFirstChild(); child != null; child = rootElem.getFirstChild()) { + collectorElem.appendChild(rootElem.removeChild(child)); + } + rootElem.appendChild(collectorElem); + } + + private Element findChild(Element parentElem, String name, String attr, String attrValue){ + Element cfgElem = null; + NodeList cfgList = parentElem.getElementsByTagName(name); + if (cfgList.getLength() > 0) { + // find per file collector element and remove children + for (int i = 0; i < cfgList.getLength(); ++i) { + Element cElem = (Element) cfgList.item(i); + String value = cElem.getAttribute(attr); + if (value.equals(attrValue)) { + cfgElem = cElem; + break; + } + } + } + + return cfgElem; + } + + private void clearChildren(Element cElem){ + for (Node child = cElem.getFirstChild(); child != null; + child = cElem.getFirstChild()) { + cElem.removeChild(child); + } + } + + + + /** + * @param scannerInfo + * @param rootElement + * @param doc + */ + private void saveDiscoveredScannerInfo(InfoContext context, IDiscoveredScannerInfoSerializable serializable, Document doc) { + NodeList rootList = doc.getElementsByTagName(SI_ELEM); + if (rootList.getLength() > 0) { + Element rootElem = (Element) rootList.item(0); + + // get the collector element + if(!context.isDefaultContext()){ + String instanceId = context.getInstanceId(); + + Element instanceElem = findChild(rootElem, INSTANCE_ELEM, ID_ATTR, instanceId); + + if(instanceElem == null){ + instanceElem = doc.createElement(INSTANCE_ELEM); + instanceElem.setAttribute(ID_ATTR, instanceId); + rootElem.appendChild(instanceElem); + } + + rootElem = instanceElem; + } + + // get the collector element + Element collectorElem = null; + NodeList collectorList = rootElem.getElementsByTagName(COLLECTOR_ELEM); + if (collectorList.getLength() > 0) { + // find per file collector element and remove children + for (int i = 0; i < collectorList.getLength(); ++i) { + Element cElem = (Element) collectorList.item(i); + String collectorId = cElem.getAttribute(ID_ATTR); + if (serializable.getCollectorId().equals(collectorId)) { + for (Node child = cElem.getFirstChild(); child != null; + child = cElem.getFirstChild()) { + cElem.removeChild(child); + } + collectorElem = cElem; + break; + } + } + } + if (collectorElem == null) { + // create per profile element + collectorElem = doc.createElement(COLLECTOR_ELEM); + collectorElem.setAttribute(ID_ATTR, serializable.getCollectorId()); + rootElem.appendChild(collectorElem); + } + + // Save the discovered scanner info + serializable.serialize(collectorElem); + } + } + public void saveDiscoveredScannerInfoToState(IProject project, IDiscoveredScannerInfoSerializable serializable) throws CoreException { + saveDiscoveredScannerInfoToState(project, new InfoContext(project), serializable); + } + + public void saveDiscoveredScannerInfoToState(IProject project, InfoContext context, IDiscoveredScannerInfoSerializable serializable) throws CoreException { + Document document = getDocument(project); + // Create document + try { + saveDiscoveredScannerInfo(context, serializable, document); + + // Transform the document to something we can save in a file + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(stream); + transformer.transform(source, result); + + // Save the document + try { + IPath path = getDiscoveredScannerConfigStore(project); + FileOutputStream file = new FileOutputStream(path.toFile()); + file.write(stream.toByteArray()); + file.close(); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } + + // Close the streams + stream.close(); + } catch (TransformerException e) { + MakeCorePlugin.log(e); + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } catch (IOException e) { + MakeCorePlugin.log(e); + throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("DiscoveredPathManager.File_Error_Message"), e)); //$NON-NLS-1$ + } + } + + public IPath getDiscoveredScannerConfigStore(IProject project) { + String fileName = project.getName() + ".sc"; //$NON-NLS-1$ + String storedFileName = null; + try { + storedFileName = project.getPersistentProperty(dscFileNameProperty); + } catch (CoreException e) { + MakeCorePlugin.log(e.getStatus()); + } + if (storedFileName != null && !storedFileName.equals(fileName)) { + // try to move 2.x file name format to 3.x file name format + movePluginStateFile(storedFileName, fileName); + } + try { + project.setPersistentProperty(dscFileNameProperty, fileName); + } catch (CoreException e) { + MakeCorePlugin.log(e.getStatus()); + } + + return MakeCorePlugin.getWorkingDirectory().append(fileName); + } + + /** + * @param delta + */ + public void updateScannerConfigStore(IResourceDelta delta) { + try { + delta.accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) throws CoreException { + IResource resource = delta.getResource(); + if (resource instanceof IProject) { + IProject project = (IProject) resource; + int kind = delta.getKind(); + switch (kind) { + case IResourceDelta.REMOVED: + if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) { + // project renamed + IPath newPath = delta.getMovedToPath(); + IProject newProject = delta.getResource().getWorkspace(). + getRoot().getProject(newPath.toString()); + scProjectRenamed(project, newProject); + } + else { + // project deleted + scProjectDeleted(project); + } + // remove from cache + fDocumentMap.put(project, null); + } + return false; + } + return true; + } + + }); + } + catch (CoreException e) { + MakeCorePlugin.log(e); + } + } + + private void scProjectDeleted(IProject project) { + String scFileName = project.getName() + ".sc"; //$NON-NLS-1$ + deletePluginStateFile(scFileName); + } + + /** + * @param scFileName + */ + private void deletePluginStateFile(String scFileName) { + IPath path = MakeCorePlugin.getWorkingDirectory().append(scFileName); + File file = path.toFile(); + if (file.exists()) { + file.delete(); + } + } + + private void scProjectRenamed(IProject project, IProject newProject) { + String scOldFileName = project.getName() + ".sc"; //$NON-NLS-1$ + String scNewFileName = newProject.getName() + ".sc"; //$NON-NLS-1$ + movePluginStateFile(scOldFileName, scNewFileName); + try { + newProject.setPersistentProperty(dscFileNameProperty, scNewFileName); + } + catch (CoreException e) { + MakeCorePlugin.log(e); + } + } + + /** + * @param oldFileName + * @param newFileName + */ + private void movePluginStateFile(String oldFileName, String newFileName) { + IPath oldPath = MakeCorePlugin.getWorkingDirectory().append(oldFileName); + IPath newPath = MakeCorePlugin.getWorkingDirectory().append(newFileName); + File oldFile = oldPath.toFile(); + File newFile = newPath.toFile(); + if (oldFile.exists()) { + oldFile.renameTo(newFile); + } + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/PerFileDiscoveredPathContainer.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/PerFileDiscoveredPathContainer.java new file mode 100644 index 00000000000..0248fd7ec72 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/PerFileDiscoveredPathContainer.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.model.IPathEntryContainerExtension; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +public class PerFileDiscoveredPathContainer extends DiscoveredPathContainer + implements IPathEntryContainerExtension { + + public PerFileDiscoveredPathContainer(IProject project) { + super(project); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.IPathEntryContainerExtension#getPathEntries(org.eclipse.core.runtime.IPath, int) + */ + public IPathEntry[] getPathEntries(IPath path, int mask) { + ArrayList entries = new ArrayList(); + try { + IDiscoveredPathInfo info = MakeCorePlugin.getDefault().getDiscoveryManager().getDiscoveredInfo(fProject); + if (info instanceof IPerFileDiscoveredPathInfo) { + IPerFileDiscoveredPathInfo filePathInfo = (IPerFileDiscoveredPathInfo) info; + + if ((mask & IPathEntry.CDT_INCLUDE) != 0) { + IPath[] includes = filePathInfo.getIncludePaths(path); + for (int i = 0; i < includes.length; i++) { + // add as a system include path + entries.add(CoreModel.newIncludeEntry(path, Path.EMPTY, includes[i], true)); + } + includes = filePathInfo.getQuoteIncludePaths(path); + for (int i = 0; i < includes.length; i++) { + // add as a local include path + entries.add(CoreModel.newIncludeEntry(path, Path.EMPTY, includes[i], false)); + } + } + if ((mask & IPathEntry.CDT_MACRO) != 0) { + Map syms = filePathInfo.getSymbols(path); + for (Iterator iter = syms.entrySet().iterator(); iter.hasNext(); ) { + Entry entry = (Entry)iter.next(); + entries.add(CoreModel.newMacroEntry(path, (String)entry.getKey(), (String)entry.getValue())); //$NON-NLS-1$ + } + } + // compare the resource with include and macros files + IPath fullResPath = fProject.getWorkspace().getRoot().getFile(path).getLocation(); + if (fullResPath == null) { + fullResPath = path; + } + if ((mask & IPathEntry.CDT_INCLUDE_FILE) != 0) { + IPath[] includeFiles = filePathInfo.getIncludeFiles(path); + for (int i = 0; i < includeFiles.length; i++) { + if (!includeFiles[i].equals(fullResPath)) { + entries.add(CoreModel.newIncludeFileEntry(path, includeFiles[i])); + } + } + } + if ((mask & IPathEntry.CDT_MACRO_FILE) != 0) { + IPath[] imacrosFiles = filePathInfo.getMacroFiles(path); + for (int i = 0; i < imacrosFiles.length; i++) { + if (!imacrosFiles[i].equals(fullResPath)) { + entries.add(CoreModel.newMacroFileEntry(path, imacrosFiles[i])); + } + } + } + } + } + catch (CoreException e) { + // + } + return (IPathEntry[]) entries.toArray(new IPathEntry[entries.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.IPathEntryContainerExtension#isEmpty(org.eclipse.core.runtime.IPath) + */ + public boolean isEmpty(IPath path) { + IDiscoveredPathInfo info; + try { + info = MakeCorePlugin.getDefault().getDiscoveryManager().getDiscoveredInfo(fProject); + if (info instanceof IPerFileDiscoveredPathInfo) { + IPerFileDiscoveredPathInfo filePathInfo = (IPerFileDiscoveredPathInfo) info; + return filePathInfo.isEmpty(path); + } + } catch (CoreException e) { + } + return false; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java new file mode 100644 index 00000000000..170adaf22cc --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java @@ -0,0 +1,384 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ + +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.Map; + +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; +import org.eclipse.core.runtime.Status; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.MakeProjectNature; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo; +import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigNature; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; + +/** + * Creates a ScannerConfigBuilderInfo variant + * @author vhirsl + */ +public class ScannerConfigInfoFactory { + private static final String PREFIX = MakeCorePlugin.getUniqueIdentifier(); + + static final String BUILD_SCANNER_CONFIG_ENABLED = PREFIX + ".ScannerConfigDiscoveryEnabled"; //$NON-NLS-1$ + static final String MAKE_BUILDER_PARSER_ENABLED = PREFIX + ".makeBuilderParserEnabled"; //$NON-NLS-1$ + static final String MAKE_BUILDER_PARSER_ID = PREFIX + ".makeBuilderParserId"; //$NON-NLS-1$ + static final String ESI_PROVIDER_COMMAND_ENABLED = PREFIX + ".esiProviderCommandEnabled"; //$NON-NLS-1$ + static final String USE_DEFAULT_ESI_PROVIDER_CMD = PREFIX + ".useDefaultESIProviderCmd"; //$NON-NLS-1$ + static final String ESI_PROVIDER_COMMAND = PREFIX + ".esiProviderCommand"; //$NON-NLS-1$ + static final String ESI_PROVIDER_ARGUMENTS = PREFIX + ".esiProviderArguments"; //$NON-NLS-1$ + static final String ESI_PROVIDER_PARSER_ID = PREFIX + ".esiProviderParserId"; //$NON-NLS-1$ + static final String SI_PROBLEM_GENERATION_ENABLED = PREFIX + ".siProblemGenerationEnabled"; //$NON-NLS-1$ + /** + * @since 3.0 + */ + static final String SI_PROFILE_ID = PREFIX + ".siProfileId"; //$NON-NLS-1$ + + /** + * + * @author vhirsl + */ + private abstract static class Store implements IScannerConfigBuilderInfo { + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isAutoDiscoveryEnabled() + */ + public boolean isAutoDiscoveryEnabled() { + return getBoolean(BUILD_SCANNER_CONFIG_ENABLED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setAutoDiscoveryEnabled(boolean) + */ + public void setAutoDiscoveryEnabled(boolean enabled) throws CoreException { + putString(BUILD_SCANNER_CONFIG_ENABLED, Boolean.toString(enabled)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isMakeBuilderConsoleParserEnabled() + */ + public boolean isMakeBuilderConsoleParserEnabled() { + if (getString(MAKE_BUILDER_PARSER_ENABLED) == null || + getString(MAKE_BUILDER_PARSER_ENABLED).length() == 0) { // if no property then default to true + return true; + } + return getBoolean(MAKE_BUILDER_PARSER_ENABLED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setMakeBuilderConsoleParserEnabled(boolean) + */ + public void setMakeBuilderConsoleParserEnabled(boolean enabled) throws CoreException { + putString(MAKE_BUILDER_PARSER_ENABLED, Boolean.toString(enabled)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getMakeBuilderConsoleParserId() + */ + public String getMakeBuilderConsoleParserId() { + String parserId = getString(MAKE_BUILDER_PARSER_ID); + if (parserId == null || parserId.length() == 0) { + String[] parserIds = MakeCorePlugin.getDefault(). + getScannerInfoConsoleParserIds("makeBuilder"); //$NON-NLS-1$ + // the default is the first one in the registry + parserId = parserIds[0]; + } + return parserId; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setMakeBuilderConsoleParserId(java.lang.String) + */ + public void setMakeBuilderConsoleParserId(String parserId) throws CoreException { + putString(MAKE_BUILDER_PARSER_ID, parserId); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isESIProviderCommandEnabled() + */ + public boolean isESIProviderCommandEnabled() { + if (getString(ESI_PROVIDER_COMMAND_ENABLED) == null || + getString(ESI_PROVIDER_COMMAND_ENABLED).length() == 0) { // if no property then default to true + return true; + } + return getBoolean(ESI_PROVIDER_COMMAND_ENABLED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderCommandEnabled(boolean) + */ + public void setESIProviderCommandEnabled(boolean enabled) throws CoreException { + putString(ESI_PROVIDER_COMMAND_ENABLED, Boolean.toString(enabled)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isDefaultESIProviderCmd() + */ + public boolean isDefaultESIProviderCmd() { + if (getString(USE_DEFAULT_ESI_PROVIDER_CMD) == null || + getString(USE_DEFAULT_ESI_PROVIDER_CMD).length() == 0) { // if no property then default to true + return true; + } + return getBoolean(USE_DEFAULT_ESI_PROVIDER_CMD); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setUseDefaultESIProviderCmd(boolean) + */ + public void setUseDefaultESIProviderCmd(boolean on) throws CoreException { + putString(USE_DEFAULT_ESI_PROVIDER_CMD, Boolean.toString(on)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderCommand() + */ + public IPath getESIProviderCommand() { + if (isDefaultESIProviderCmd()) { + String command = getESIProviderParameter("defaultCommand"); //$NON-NLS-1$ + if (command == null) { + return new Path("gcc"); //$NON-NLS-1$ + } + return new Path(command); + } + return new Path(getString(ESI_PROVIDER_COMMAND)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderCommand(org.eclipse.core.runtime.IPath) + */ + public void setESIProviderCommand(IPath command) throws CoreException { + putString(ESI_PROVIDER_COMMAND, command.toString()); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderArguments() + */ + public String getESIProviderArguments() { + if (isDefaultESIProviderCmd()) { + String attributes = getESIProviderParameter("defaultAttributes"); //$NON-NLS-1$ + if (attributes == null) { + attributes = "-E -P -v -dD ${plugin_state_location}/${specs_file}"; //$NON-NLS-1$ + } + return attributes; + } + return getString(ESI_PROVIDER_ARGUMENTS); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderArguments(java.lang.String) + */ + public void setESIProviderArguments(String args) throws CoreException { + putString(ESI_PROVIDER_ARGUMENTS, args); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderConsoleParserId() + */ + public String getESIProviderConsoleParserId() { + String parserId = getString(ESI_PROVIDER_PARSER_ID); + if (parserId == null || parserId.length() == 0) { + String[] parserIds = MakeCorePlugin.getDefault(). + getScannerInfoConsoleParserIds("externalScannerInfoProvider"); //$NON-NLS-1$ + // the default is the first one in the registry + parserId = parserIds[0]; + } + return parserId; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderConsoleParserId(java.lang.String) + */ + public void setESIProviderConsoleParserId(String parserId) throws CoreException { + putString(ESI_PROVIDER_PARSER_ID, parserId); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isSIProblemGenerationEnabled() + */ + public boolean isSIProblemGenerationEnabled() { + if (getString(SI_PROBLEM_GENERATION_ENABLED) == null || + getString(SI_PROBLEM_GENERATION_ENABLED).length() == 0) { // if no property then default to true + return true; + } + return getBoolean(SI_PROBLEM_GENERATION_ENABLED); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setSIProblemGenerationEnabled(boolean) + */ + public void setSIProblemGenerationEnabled(boolean enabled) throws CoreException { + putString(SI_PROBLEM_GENERATION_ENABLED, Boolean.toString(enabled)); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getProfileId() + */ + public String getProfileId() { + String profileId = getString(SI_PROFILE_ID); + if (profileId == null || profileId.length() == 0) { + profileId = ScannerConfigProfileManager.getDefaultSIProfileId(); + // the default is the first one in the registry + } + return profileId; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setProfileId(java.lang.String) + */ + public void setProfileId(String profileId) throws CoreException { + putString(SI_PROFILE_ID, profileId); + } + + protected boolean getBoolean(String property) { + return Boolean.valueOf(getString(property)).booleanValue(); + } + + protected abstract String getBuilderID(); + protected abstract String getString(String property); + protected abstract void putString(String name, String value) throws CoreException; + + protected String getESIProviderParameter(String name) { + IExtension extension = + Platform.getExtensionRegistry().getExtension( + MakeCorePlugin.getUniqueIdentifier(), + MakeCorePlugin.EXTERNAL_SI_PROVIDER_SIMPLE_ID, + // TODO VMIR make this configurable + MakeCorePlugin.DEFAULT_EXTERNAL_SI_PROVIDER_ID); + if (extension == null) + return null; + IConfigurationElement[] configs = extension.getConfigurationElements(); + if (configs.length == 0) + return null; + IConfigurationElement[] runElement = configs[0].getChildren("run"); //$NON-NLS-1$ + IConfigurationElement[] paramElement = runElement[0].getChildren("parameter"); //$NON-NLS-1$ + for (int i = 0; i < paramElement.length; i++) { + if (paramElement[i].getAttribute("name").equals(name)) { //$NON-NLS-1$ + return paramElement[i].getAttribute("value"); //$NON-NLS-1$ + } + } + return null; + } + } + + private static class Preference extends Store { + private Preferences prefs; + private String builderID; + private boolean useDefaults; + + Preference(Preferences prefs, String builderID, boolean useDefaults) { + this.prefs = prefs; + this.builderID = builderID; + this.useDefaults = useDefaults; + } + + protected void putString(String name, String value) { + if (useDefaults) { + prefs.setDefault(name, value); + } else { + prefs.setValue(name, value); + } + } + + protected String getString(String property) { + if (useDefaults) { + return prefs.getDefaultString(property); + } + return prefs.getString(property); + } + + protected String getBuilderID() { + return builderID; + } + } + + private static class BuildProperty extends Store { + private IProject project; + private String builderID; + private Map args; + + BuildProperty(IProject project, String builderID) throws CoreException { + this.project = project; + this.builderID = builderID; + ICommand builder = ScannerConfigNature.getBuildSpec(project.getDescription(), builderID); + if (builder == null) { + throw new CoreException(new Status(IStatus.ERROR, + MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("ScannerConfigInfoFactory.Missing_Builder")//$NON-NLS-1$ + + builderID, null)); + } + args = builder.getArguments(); + } + + protected void putString(String name, String value) throws CoreException { + String curValue = (String) args.get(name); + if (curValue != null && curValue.equals(value)) { + return; + } + IProjectDescription description = project.getDescription(); + ICommand builder = ScannerConfigNature.getBuildSpec(description, builderID); + args.put(name, value); + builder.setArguments(args); + MakeProjectNature.setBuildSpec(description, builder); + project.setDescription(description, null); + } + + protected String getString(String name) { + String value = (String) args.get(name); + return value == null ? "" : value; //$NON-NLS-1$ + } + + protected String getBuilderID() { + return builderID; + } + } + + private static class BuildArguments extends Store { + private Map args; + private String builderID; + + BuildArguments(Map args, String builderID) { + this.args = args; + this.builderID = builderID; + } + + protected void putString(String name, String value) { + args.put(name, value); + } + + protected String getString(String name) { + return (String) args.get(name); + } + + protected String getBuilderID() { + return builderID; + } + } + + public static IScannerConfigBuilderInfo create(Preferences prefs, String builderID, boolean useDefaults) { + return new ScannerConfigInfoFactory.Preference(prefs, builderID, useDefaults); + } + + public static IScannerConfigBuilderInfo create(IProject project, String builderID) throws CoreException { + return new ScannerConfigInfoFactory.BuildProperty(project, builderID); + } + + public static IScannerConfigBuilderInfo create(Map args, String builderID) { + return new ScannerConfigInfoFactory.BuildArguments(args, builderID); + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigUtil.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigUtil.java new file mode 100644 index 00000000000..476d5d66b88 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigUtil.java @@ -0,0 +1,290 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.make.internal.core.scannerconfig.util.SymbolEntry; +import org.eclipse.core.runtime.IPath; + +/** + * Utility class that handles some Scanner Config specifig collection conversions + * + * @author vhirsl + */ +public final class ScannerConfigUtil { + /** + * Adds all new discovered symbols/values to the existing ones. + * + * @param sumSymbols - a map of [String, Map] where Map is a SymbolEntry + * @param symbols + * @return boolean + */ + public static boolean scAddSymbolsList2SymbolEntryMap(Map sumSymbols, List symbols, boolean active) { + boolean rc = false; + for (Iterator i = symbols.iterator(); i.hasNext(); ) { + String symbol = (String) i.next(); + String key; + String value = null; + int index = symbol.indexOf("="); //$NON-NLS-1$ + if (index != -1) { + key = symbol.substring(0, index).trim(); + value = symbol.substring(index + 1).trim(); + } else { + key = symbol.trim(); + } + SymbolEntry sEntry = (SymbolEntry) sumSymbols.get(key); + if (sEntry == null) { + // make only the first one to be active + sEntry = new SymbolEntry(key, value, true); + rc = true; + } + else { + rc |= sEntry.add(value, active); + } + sumSymbols.put(key, sEntry); + } + return rc; + } + + /** + * Gets all discovered symbols with either active or removed values + * @param sumSymbols + * @param active - false = removed + * @return + */ + public static List scSymbolsSymbolEntryMap2List(Map sumSymbols, boolean active) { + Set symbols = sumSymbols.entrySet(); + List rv = new ArrayList(symbols.size()); + for (Iterator i = symbols.iterator(); i.hasNext(); ) { + SymbolEntry sEntry = (SymbolEntry) ((Map.Entry) i.next()).getValue(); + if (active) { + rv.addAll(sEntry.getActiveRaw()); + } + else { + rv.addAll(sEntry.getRemovedRaw()); + } + } + return rv; + } + + /** + * MapsSymbolEntryMap to a plain Map + * + * @param sumSymbols (in) - discovered symbols in SymbolEntryMap + * @return - active symbols as a plain Map + */ + public static Map scSymbolEntryMap2Map(Map sumSymbols) { + Map rv = new HashMap(); + for (Iterator i = sumSymbols.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + SymbolEntry values = (SymbolEntry) sumSymbols.get(key); + for (Iterator j = values.getValuesOnly(true).iterator(); j.hasNext(); ) { + String value = (String) j.next(); + rv.put(key, value); // multiple active values will be condensed to one !!! + } + } + return rv; + } + + /** + * Adds a single symbol definition string ("DEBUG_LEVEL=4") to the SymbolEntryMap + * + * @param symbols + * @param symbol + * @param active + */ + public static boolean scAddSymbolString2SymbolEntryMap(Map symbols, String symbol, boolean active) { + boolean rc = false; + String key; + String value = null; + int index = symbol.indexOf("="); //$NON-NLS-1$ + if (index != -1) { + key = getSymbolKey(symbol); + value = getSymbolValue(symbol); + } else { + key = symbol.trim(); + } + SymbolEntry sEntry = (SymbolEntry) symbols.get(key); + if (sEntry == null) { + // make only the first one to be active + sEntry = new SymbolEntry(key, value, active); + rc = true; + } + else { + rc |= sEntry.add(value, active); + } + symbols.put(key, sEntry); + return rc; + } + + /** + * @param result (out) + * @param addend (in) + * @return + */ + public static boolean scAddSymbolEntryMap2SymbolEntryMap(Map result, Map addend) { + boolean rc = false; + for (Iterator i = addend.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + if (result.keySet().contains(key)) { + SymbolEntry rSE = (SymbolEntry) result.get(key); + SymbolEntry aSE = (SymbolEntry) addend.get(key); + List activeValues = rSE.getActiveRaw(); + for (Iterator j = aSE.getActiveRaw().iterator(); j.hasNext(); ) { + String aValue = (String) j.next(); + if (!activeValues.contains(aValue)) { + // result does not contain addend's value; add it + rSE.add(getSymbolValue(aValue), true); + rc |= true; + } + } + List removedValues = rSE.getRemovedRaw(); + for (Iterator j = aSE.getRemovedRaw().iterator(); j.hasNext(); ) { + String aValue = (String) j.next(); + if (!removedValues.contains(aValue)) { + // result does not contain addend's value; add it + rSE.add(getSymbolValue(aValue), false); + rc |= true; + } + } + } + else { + // result does not contain the symbol; add it + // shallow copy + SymbolEntry aSymbolEntry = (SymbolEntry) addend.get(key); + result.put(key, aSymbolEntry); + rc |= true; + } + } + return rc; + } + + /** + * Returns a symbol key (i.e. for DEF=1 returns DEF) + * + * @param symbol - in + * @param key - out + */ + public static String getSymbolKey(String symbol) { + int index = symbol.indexOf('='); + if (index != -1) { + return symbol.substring(0, index).trim(); + } + return symbol; + } + + /** + * Returns a symbol value (i.e. for DEF=1 returns 1) + * + * @param symbol - in + * @param key - out (may be null) + */ + public static String getSymbolValue(String symbol) { + int index = symbol.indexOf('='); + if (index != -1) { + return symbol.substring(index+1).trim(); + } + return null; + } + + /** + * Removes a symbol value from the symbol entry. If it was an only value than + * it symbol entry will be removed alltogether. + * + * @param symbol + * @param symbolEntryMap map of [symbol's key, symbolEntry] + */ + public static void removeSymbolEntryValue(String symbol, Map symbolEntryMap) { + String key = getSymbolKey(symbol); + String value = getSymbolValue(symbol); + // find it in the discoveredSymbols Map of SymbolEntries + SymbolEntry se = (SymbolEntry) symbolEntryMap.get(key); + if (se != null) { + se.remove(value); + if (se.numberOfValues() == 0) { + symbolEntryMap.remove(key); + } + } + } + + /** + * Swaps two include paths in the include paths Map. + * Used by Up/Down discovered paths + * + * @param sumPaths + * @param index1 + * @param index2 + * @return new map of include paths + */ + public static LinkedHashMap swapIncludePaths(LinkedHashMap sumPaths, int index1, int index2) { + int size = sumPaths.size(); + if (index1 == index2 || + !(index1 >= 0 && index1 < size && + index2 >= 0 && index2 < size)) { + return sumPaths; + } + ArrayList pathKeyList = new ArrayList(sumPaths.keySet()); + String temp1 = (String) pathKeyList.get(index1); + String temp2 = (String) pathKeyList.get(index2); + pathKeyList.set(index1, temp2); + pathKeyList.set(index2, temp1); + + LinkedHashMap newSumPaths = new LinkedHashMap(sumPaths.size()); + for (Iterator i = pathKeyList.iterator(); i.hasNext(); ) { + String key = (String) i.next(); + newSumPaths.put(key, sumPaths.get(key)); + } + return newSumPaths; + } + + /** + * Tokenizes string with quuotes + * + * @param String + * @return String[] + */ + public static String[] tokenizeStringWithQuotes(String line, String quoteStyle) { + ArrayList allTokens = new ArrayList(); + String[] tokens = line.split(quoteStyle); + for (int i = 0; i < tokens.length; ++i) { + if (i % 2 == 0) { // even tokens need further tokenization + String[] sTokens = tokens[i].split("\\s+"); //$NON-NLS-1$ + for (int j = 0; j < sTokens.length; allTokens.add(sTokens[j++])); + } + else { + allTokens.add(tokens[i]); + } + } + return (String[]) allTokens.toArray(new String[allTokens.size()]); + } + + /** + * Converts array of IPath-s to array of String-s + * + * @param paths + * @return + */ + public static String[] iPathArray2StringArray(IPath[] paths) { + String[] rv = new String[paths.length]; + for (int i = 0; i < paths.length; ++i) { + rv[i] = paths[i].toString(); + } + return rv; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java new file mode 100644 index 00000000000..200a4172b07 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig; + +import java.io.OutputStream; + +import org.eclipse.cdt.core.IMarkerGenerator; +import org.eclipse.cdt.internal.core.ConsoleOutputSniffer; +import org.eclipse.cdt.make.core.MakeBuilderUtil; +import org.eclipse.cdt.make.core.MakeBuilder; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2Set; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigNature; +import org.eclipse.cdt.make.internal.core.scannerconfig2.SCProfileInstance; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +/** + * A factory that creates a ConsoleOutputStreamSniffer, + * ScannerInfoConsoleParser and optionally a ScannerInfoConsoleParserUtility. + * + * @author vhirsl + */ +public class ScannerInfoConsoleParserFactory { + + /** + * Creates a ConsoleOutputStreamSniffer, make builder scanner info console parser + * and a utility. + * + * @param outputStream + * @param errorStream + * @param currentProject + * @param providerId + * @param scBuildInfo + * @param markerGenerator + * @return ConsoleOutputSniffer + */ + public static ConsoleOutputSniffer getESIProviderOutputSniffer( + OutputStream outputStream, + OutputStream errorStream, + IProject currentProject, + String providerId, + IScannerConfigBuilderInfo2 scBuildInfo, + IScannerInfoCollector collector, + IMarkerGenerator markerGenerator) { + return getESIProviderOutputSniffer(outputStream, errorStream, currentProject, new InfoContext(currentProject), providerId, scBuildInfo, collector, markerGenerator); + } + /** + * Creates a ConsoleOutputStreamSniffer, make builder scanner info console parser + * and a utility. + * + * @param outputStream + * @param errorStream + * @param currentProject + * @param providerId + * @param scBuildInfo + * @param markerGenerator + * @return ConsoleOutputSniffer + */ + public static ConsoleOutputSniffer getESIProviderOutputSniffer( + OutputStream outputStream, + OutputStream errorStream, + IProject currentProject, + InfoContext context, + String providerId, + IScannerConfigBuilderInfo2 scBuildInfo, + IScannerInfoCollector collector, + IMarkerGenerator markerGenerator) { + if (scBuildInfo.isProviderOutputParserEnabled(providerId)) { + // get the ESIProvider console parser + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(currentProject, context, scBuildInfo.getSelectedProfileId()); + IScannerInfoConsoleParser clParser = profileInstance.createExternalScannerInfoParser(providerId); + IPath buildDirectory = MakeBuilderUtil.getBuildDirectory(currentProject, MakeBuilder.BUILDER_ID); + clParser.startup(currentProject, buildDirectory, collector, markerGenerator); + // create an output stream sniffer + return new ConsoleOutputSniffer(outputStream, errorStream, new + IScannerInfoConsoleParser[] {clParser}); + } + return null; + } + + /** + * Creates a ConsoleOutputStreamSniffer, ESI provider scanner info console parser + * and a utility. + * + * @param outputStream + * @param errorStream + * @param currentProject + * @param workingDirectory + * @param buildInfo + * @param markerGenerator + * @param IScannerInfoCollector2 + * @return ConsoleOutputSniffer + */ + public static ConsoleOutputSniffer getMakeBuilderOutputSniffer( + OutputStream outputStream, + OutputStream errorStream, + IProject currentProject, + IPath workingDirectory, + IScannerConfigBuilderInfo2 scBuildInfo, + IMarkerGenerator markerGenerator, + IScannerInfoCollector collector) { + return getMakeBuilderOutputSniffer(outputStream, errorStream, currentProject, new InfoContext(currentProject), workingDirectory, scBuildInfo, markerGenerator, collector); + } + + /** + * Creates a ConsoleOutputStreamSniffer, ESI provider scanner info console parser + * and a utility. + * + * @param outputStream + * @param errorStream + * @param currentProject + * @param workingDirectory + * @param buildInfo + * @param markerGenerator + * @param IScannerInfoCollector2 + * @return ConsoleOutputSniffer + */ + public static ConsoleOutputSniffer getMakeBuilderOutputSniffer( + OutputStream outputStream, + OutputStream errorStream, + IProject currentProject, + InfoContext context, + IPath workingDirectory, + IScannerConfigBuilderInfo2 scBuildInfo, + IMarkerGenerator markerGenerator, + IScannerInfoCollector collector) { + try { + // get the SC builder settings + if (currentProject.hasNature(ScannerConfigNature.NATURE_ID)) { + if (scBuildInfo == null) { + try { + IScannerConfigBuilderInfo2Set container = ScannerConfigProfileManager. + createScannerConfigBuildInfo2Set(currentProject); + scBuildInfo = container.getInfo(context); + } + catch (CoreException e) { + // builder not installed or disabled + } + } + if (scBuildInfo != null && + scBuildInfo.isAutoDiscoveryEnabled() && + scBuildInfo.isBuildOutputParserEnabled()) { + // get the make builder console parser + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(currentProject, context, scBuildInfo.getSelectedProfileId()); + IScannerInfoConsoleParser clParser = profileInstance.createBuildOutputParser(); + if (collector == null) { + collector = profileInstance.getScannerInfoCollector(); + } + clParser.startup(currentProject, workingDirectory, collector, + scBuildInfo.isProblemReportingEnabled() ? markerGenerator : null); + // create an output stream sniffer + return new ConsoleOutputSniffer(outputStream, errorStream, new + IScannerInfoConsoleParser[] {clParser}); + } + } + } + catch (CoreException e) { + MakeCorePlugin.log(e.getStatus()); + } + return null; + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java new file mode 100644 index 00000000000..586f3771272 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParser.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; +import org.eclipse.cdt.make.internal.core.scannerconfig2.SCProfileInstance; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfile.BuildOutputProvider; +import org.eclipse.core.resources.IProject; + +/** + * Common stuff for all GNU build output parsers + * + * @author vhirsl + */ +public abstract class AbstractGCCBOPConsoleParser implements IScannerInfoConsoleParser { + private static final String[] COMPILER_INVOCATION = { + "gcc", "g++", "cc", "c++" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + }; + + private IProject project; + private IScannerInfoCollector collector; + + private boolean bMultiline = false; + private String sMultiline = ""; //$NON-NLS-1$ + + /** + * @return Returns the project. + */ + protected IProject getProject() { + return project; + } + /** + * @return Returns the collector. + */ + protected IScannerInfoCollector getCollector() { + return collector; + } + + public void startup(IProject project, IScannerInfoCollector collector) { + this.project = project; + this.collector = collector; + } + + /** + * Returns array of additional compiler commands to look for + * + * @return String[] + */ + public String[] getCompilerCommands() { + if (project != null) { + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(project, ScannerConfigProfileManager.NULL_PROFILE_ID); + BuildOutputProvider boProvider = profileInstance.getProfile().getBuildOutputProviderElement(); + if (boProvider != null) { + String compilerCommandsString = boProvider.getScannerInfoConsoleParser().getCompilerCommands(); + if (compilerCommandsString != null && compilerCommandsString.length() > 0) { + String[] compilerCommands = compilerCommandsString.split(",\\s+"); //$NON-NLS-1$ + if (compilerCommands.length > 0) { + String[] compilerInvocation = new String[COMPILER_INVOCATION.length + compilerCommands.length]; + System.arraycopy(COMPILER_INVOCATION, 0, compilerInvocation, 0, COMPILER_INVOCATION.length); + System.arraycopy(compilerCommands, 0, compilerInvocation, COMPILER_INVOCATION.length, compilerCommands.length); + return compilerInvocation; + } + } + } + } + return COMPILER_INVOCATION; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#processLine(java.lang.String) + */ + public boolean processLine(String line) { + boolean rc = false; + // check for multiline commands (ends with '\') + if (line.endsWith("\\")) { //$NON-NLS-1$ + sMultiline += line.substring(0, line.length()-1);// + " "; + bMultiline = true; + return rc; + } + if (bMultiline) { + line = sMultiline + line; + bMultiline = false; + sMultiline = ""; //$NON-NLS-1$ + } + TraceUtil.outputTrace("AbstractGCCBOPConsoleParser parsing line: [", line, "]"); //$NON-NLS-1$ //$NON-NLS-2$ + // make\[[0-9]*\]: error_desc + int firstColon= line.indexOf(':'); + String make = line.substring(0, firstColon + 1); + if (firstColon != -1 && make.indexOf("make") != -1) { //$NON-NLS-1$ + boolean enter = false; + String msg = line.substring(firstColon + 1).trim(); + if ((enter = msg.startsWith("Entering directory")) || //$NON-NLS-1$ + (msg.startsWith("Leaving directory"))) { //$NON-NLS-1$ + int s = msg.indexOf('`'); + int e = msg.indexOf('\''); + if (s != -1 && e != -1) { + String dir = msg.substring(s+1, e); + if (getUtility() != null) { + getUtility().changeMakeDirectory(dir, getDirectoryLevel(line), enter); + } + return rc; + } + } + } + // call sublclass to process a single line + return processSingleLine(line); + } + + private int getDirectoryLevel(String line) { + int s = line.indexOf('['); + int num = 0; + if (s != -1) { + int e = line.indexOf(']'); + String number = line.substring(s + 1, e).trim(); + try { + num = Integer.parseInt(number); + } catch (NumberFormatException exc) { + } + } + return num; + } + + protected abstract boolean processSingleLine(String line); + protected abstract AbstractGCCBOPConsoleParserUtility getUtility(); + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#shutdown() + */ + public void shutdown() { + if (getUtility() != null) { + getUtility().reportProblems(); + } + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParserUtility.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParserUtility.java new file mode 100644 index 00000000000..60a029e8aea --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/AbstractGCCBOPConsoleParserUtility.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Vector; + +import org.eclipse.cdt.core.IMarkerGenerator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Common utilities for GCC build output console parsers + * + * @author vhirsl + */ +public abstract class AbstractGCCBOPConsoleParserUtility { + private IProject project; + private IPath fBaseDirectory; + private Vector fDirectoryStack; + private IMarkerGenerator fMarkerGenerator; + private ArrayList fErrors; + + /** + * + */ + public AbstractGCCBOPConsoleParserUtility(IProject project, IPath workingDirectory, + IMarkerGenerator markerGenerator) { + fDirectoryStack = new Vector(); + fErrors = new ArrayList(); + this.project = project; + fBaseDirectory = project.getLocation(); + if (workingDirectory != null) { + pushDirectory(workingDirectory); + } + } + + /** + * @return Returns the fBaseDirectory. + */ + protected IPath getBaseDirectory() { + return fBaseDirectory; + } + /** + * @return Returns the fDirectoryStack. + */ + protected Vector getDirectoryStack() { + return fDirectoryStack; + } + /** + * @return Returns the fErrors. + */ + protected ArrayList getErrors() { + return fErrors; + } + /** + * @return Returns the fMarkerGenerator. + */ + protected IMarkerGenerator getMarkerGenerator() { + return fMarkerGenerator; + } + /** + * @return Returns the project. + */ + protected IProject getProject() { + return project; + } + + public IPath getWorkingDirectory() { + if (fDirectoryStack.size() != 0) { + return (IPath) fDirectoryStack.lastElement(); + } + // Fallback to the Project Location + // FIXME: if the build did not start in the Project ? + return fBaseDirectory; + } + + protected void pushDirectory(IPath dir) { + if (dir != null) { + IPath pwd = null; + if (fBaseDirectory.isPrefixOf(dir)) { + pwd = dir.removeFirstSegments(fBaseDirectory.segmentCount()); + } else { + // check if it is a cygpath + pwd= convertCygpath(dir); + } + fDirectoryStack.addElement(pwd); + } + } + + public static IPath convertCygpath(IPath path) { + if (path.segmentCount() > 1 && path.segment(0).equals("cygdrive")) { //$NON-NLS-1$ + StringBuffer buf = new StringBuffer(2); + buf.append(Character.toUpperCase(path.segment(1).charAt(0))); + buf.append(':'); + path = path.removeFirstSegments(2); + path = path.setDevice(buf.toString()); + path = path.makeAbsolute(); + } + return path; + } + + protected IPath popDirectory() { + int i = getDirectoryLevel(); + if (i != 0) { + IPath dir = (IPath) fDirectoryStack.lastElement(); + fDirectoryStack.removeElementAt(i - 1); + return dir; + } + return new Path(""); //$NON-NLS-1$ + } + + protected int getDirectoryLevel() { + return fDirectoryStack.size(); + } + + public void changeMakeDirectory(String dir, int dirLevel, boolean enterDir) { + if (enterDir) { + /* Sometimes make screws up the output, so + * "leave" events can't be seen. Double-check level + * here. + */ + for (int parseLevel = getDirectoryLevel(); dirLevel < parseLevel; parseLevel = getDirectoryLevel()) { + popDirectory(); + } + pushDirectory(new Path(dir)); + } else { + popDirectory(); + /* Could check to see if they match */ + } + } + + public boolean reportProblems() { + boolean reset = false; + for (Iterator iter = fErrors.iterator(); iter.hasNext(); ) { + Problem problem = (Problem) iter.next(); + if (problem.severity == IMarkerGenerator.SEVERITY_ERROR_BUILD) { + reset = true; + } + if (problem.file == null) { + fMarkerGenerator.addMarker( + project, + problem.lineNumber, + problem.description, + problem.severity, + problem.variableName); + } else { + fMarkerGenerator.addMarker( + problem.file, + problem.lineNumber, + problem.description, + problem.severity, + problem.variableName); + } + } + fErrors.clear(); + return reset; + } + + protected class Problem { + protected IResource file; + protected int lineNumber; + protected String description; + protected int severity; + protected String variableName; + + public Problem(IResource file, int lineNumber, String desciption, int severity, String variableName) { + this.file = file; + this.lineNumber = lineNumber; + this.description = desciption; + this.severity = severity; + this.variableName = variableName; + } + } + + /** + * Called by the console line parsers to generate a problem marker. + */ + public void generateMarker(IResource file, int lineNumber, String desc, int severity, String varName) { + // No need to collect markers if marker generator is not present + if (fMarkerGenerator != null) { + Problem problem = new Problem(file, lineNumber, desc, severity, varName); + fErrors.add(problem); + } + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java new file mode 100644 index 00000000000..2e5126a63ff --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParser.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +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.CCommandDSC; +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; + + +/** + * GCC per file build output parser + * + * @author vhirsl + */ +public class GCCPerFileBOPConsoleParser extends AbstractGCCBOPConsoleParser { + private final static String[] FILE_EXTENSIONS = { + ".c", ".cc", ".cpp", ".cxx", ".C", ".CC", ".CPP", ".CXX" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + }; + private final static List FILE_EXTENSIONS_LIST = Arrays.asList(FILE_EXTENSIONS); + + private String[] compilerInvocation; + private GCCPerFileBOPConsoleParserUtility fUtil; + + /* (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 GCCPerFileBOPConsoleParserUtility(project, workingDirectory, markerGenerator) : null; + super.startup(project, collector); + + // check additional compiler commands from extension point manifest + compilerInvocation = getCompilerCommands(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#getUtility() + */ + protected AbstractGCCBOPConsoleParserUtility getUtility() { + return fUtil; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#processSingleLine(java.lang.String) + */ + protected boolean processSingleLine(String line) { + boolean rc = false; + // GCC C/C++ compiler invocation + int compilerInvocationIndex = -1; + for (int cii = 0; cii < compilerInvocation.length; ++cii) { + compilerInvocationIndex = line.indexOf(compilerInvocation[cii]); + if (compilerInvocationIndex != -1) + break; + } + if (compilerInvocationIndex == -1) + return rc; + + // expecting that compiler invocation is the first token in the line + String[] split = line.split("\\s+"); //$NON-NLS-1$ + String command = split[0]; + // verify that it is compiler invocation + int cii2 = -1; + for (int cii = 0; cii < compilerInvocation.length; ++cii) { + cii2 = command.indexOf(compilerInvocation[cii]); + if (cii2 != -1) + break; + } + if (cii2 == -1) { + TraceUtil.outputTrace("Error identifying compiler command", line, TraceUtil.EOL); //$NON-NLS-1$ + return rc; + } + // find a file name + int extensionsIndex = -1; + boolean found = false; + String filePath = null; + for (int i = 1; i < split.length; ++i) { + int k = split[i].lastIndexOf('.'); + if (k != -1 && (split[i].length() - k < 5)) { + String fileExtension = split[i].substring(k); + extensionsIndex = FILE_EXTENSIONS_LIST.indexOf(fileExtension); + if (extensionsIndex != -1) { + filePath = split[i]; + found = true; + break; + } + } + } +// for (int j = 0; j < FILE_EXTENSIONS.length; ++j) { +// if (split[i].endsWith(FILE_EXTENSIONS[j])) { +// filePath = split[i]; +// extensionsIndex = j; +// found = true; +// break; +// } +// } +// if (found) break; + if (!found) { + TraceUtil.outputTrace("Error identifying file name :1", line, TraceUtil.EOL); //$NON-NLS-1$ + return rc; + } + // sanity check + if (filePath.indexOf(FILE_EXTENSIONS[extensionsIndex]) == -1) { + TraceUtil.outputTrace("Error identifying file name :2", line, TraceUtil.EOL); //$NON-NLS-1$ + return rc; + } + if (fUtil != null) { + IPath pFilePath = fUtil.getAbsolutePath(filePath); + String shortFileName = pFilePath.removeFileExtension().lastSegment(); + + // generalize occurances of the file name + StringBuffer genericLine = new StringBuffer(); + for (int i = 0; i < split.length; i++) { + String token = split[i]; + if (token.equals("-include") || token.equals("-imacros")) { //$NON-NLS-1$ //$NON-NLS-2$ + ++i; + genericLine.append(token); + genericLine.append(' '); + } + else if (token.equals(filePath)) { + split[i] = "LONG_NAME"; //$NON-NLS-1$ + } + else if (token.startsWith(shortFileName)) { + split[i] = token.replaceFirst(shortFileName, "SHORT_NAME"); //$NON-NLS-1$ + } + genericLine.append(split[i]); + genericLine.append(' '); + } + + CCommandDSC cmd = fUtil.getNewCCommandDSC(genericLine.toString(), extensionsIndex > 0); + IPath baseDirectory = fUtil.getBaseDirectory(); + if (baseDirectory.isPrefixOf(pFilePath)) { + List cmdList = new ArrayList(); + cmdList.add(cmd); + Map sc = new HashMap(1); + sc.put(ScannerInfoTypes.COMPILER_COMMAND, cmdList); + + IPath relPath = pFilePath.removeFirstSegments(baseDirectory.segmentCount()); + //Note: We add the scannerconfig even if the resource doesnt actually + //exist below this project (which may happen when reading existing + //build logs, because resources can be created as part of the build + //and may not exist at the time of analyzing the config but re-built + //later on. + //if (getProject().exists(relPath)) { + IFile file = getProject().getFile(relPath); + getCollector().contributeToScannerConfig(file, sc); + } else { + //TODO limiting to pathes below this project means not being + //able to work with linked resources. Linked resources could + //be checked through IWorkspaceRoot.findFilesForLocation(). + TraceUtil.outputError("Build command for file outside project: "+pFilePath.toString(), line); //$NON-NLS-1$ + } + // fUtil.addGenericCommandForFile2(longFileName, genericLine); + } + return rc; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java new file mode 100644 index 00000000000..73eac867443 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileBOPConsoleParserUtility.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ +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.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 directoryCommandListMap; + private List compiledFileList; + + private List commandsList2; + + private int workingDirsN = 0; + private int commandsN = 0; + private int filesN = 0; + + + /** + * @param markerGenerator + * @param workingDirectory + * @param project + */ + public GCCPerFileBOPConsoleParserUtility(IProject project, IPath workingDirectory, IMarkerGenerator markerGenerator) { + super(project, workingDirectory, markerGenerator); + } + + /** + * Adds a mapping filename, generic_command + * @param longFileName + * @param genericLine + */ + 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 directoryCommandList = (List) directoryCommandListMap.get(workingDir); + if (directoryCommandList == null) { + directoryCommandList = new ArrayList(); + directoryCommandListMap.put(workingDir, directoryCommandList); + ++workingDirsN; + } + Map command21FileListMap = null; + for (Iterator i = directoryCommandList.iterator(); i.hasNext(); ) { + command21FileListMap = (Map) i.next(); + List fileList = (List) command21FileListMap.get(genericCommand); + if (fileList != null) { + if (!fileList.contains(longFileName)) { + fileList.add(longFileName); + ++filesN; + } + return; + } + } + command21FileListMap = new HashMap(1); + directoryCommandList.add(command21FileListMap); + ++commandsN; + List fileList = new ArrayList(); + 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 + * @param longFileName + * @param genericLine + */ + void addGenericCommandForFile2(String longFileName, String genericLine) { + // if a file name has already been added once, return + if (compiledFileList.contains(longFileName)) + return; + compiledFileList.add(longFileName); + + CCommandDSC command = getNewCCommandDSC(genericLine, false); // assume .c file type + int index = commandsList2.indexOf(command); + if (index == -1) { + commandsList2.add(command); + ++commandsN; + } + else { + command = (CCommandDSC) commandsList2.get(index); + } +// // add a file +// command.addFile(longFileName); +// ++filesN; + } + + /** + * @param genericLine + * @param cppFileType + * @return CCommandDSC compile command description + */ + public CCommandDSC getNewCCommandDSC(String genericLine, boolean cppFileType) { + CCommandDSC command = new CCommandDSC(cppFileType); + String[] tokens = genericLine.split("\\s+"); //$NON-NLS-1$ + command.addSCOption(new KVStringPair(SCDOptionsEnum.COMMAND.toString(), tokens[0])); + for (int i = 1; i < tokens.length; ++i) { + String token = tokens[i]; + //Target specific options: see GccScannerInfoConsoleParser + if (token.startsWith("-m") || //$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) { + if (token.startsWith(SCDOptionsEnum.getSCDOptionsEnum(j).toString())) { + String option = token.substring( + SCDOptionsEnum.getSCDOptionsEnum(j).toString().length()).trim(); + if (option.length() > 0) { + // ex. -I/dir + } + else if (SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.IDASH)) { + // -I- has no parameter + } + else { + // ex. -I /dir + // take a next token + ++i; + if (i < tokens.length && !tokens[i].startsWith("-")) { //$NON-NLS-1$ + option = tokens[i]; + } + else break; + } + if (option.length() > 0 && ( + SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.INCLUDE) || + SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.INCLUDE_FILE) || + SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.IMACROS_FILE) || + SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.IDIRAFTER) || + SCDOptionsEnum.getSCDOptionsEnum(j).equals(SCDOptionsEnum.ISYSTEM))) { + option = (getAbsolutePath(option)).toString(); + } + // add the pair + command.addSCOption(new KVStringPair(SCDOptionsEnum.getSCDOptionsEnum(j).toString(), option)); + break; + } + } + } + return command; + } + + /** + * @param filePath : String + * @return filePath : IPath - not <code>null</code> + */ + IPath getAbsolutePath(String filePath) { + IPath pFilePath; + if (filePath.startsWith("/")) { //$NON-NLS-1$ + return 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); + } + pFilePath = cwd.append(filePath); + } + 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 getCCommandDSCList() { + return new ArrayList(commandsList2); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileSIPConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileSIPConsoleParser.java new file mode 100644 index 00000000000..5a07a3a8fee --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCPerFileSIPConsoleParser.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.util.ArrayList; +import java.util.HashMap; +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.IScannerInfoConsoleParser; +import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; + +/** + * Console parser for generated makefile output + * + * @author vhirsl + */ +public class GCCPerFileSIPConsoleParser implements IScannerInfoConsoleParser { + private final static String INCLUDE_PREAMBLE = "#include <...>"; //$NON-NLS-1$ + private final static String QUOTE_INCLUDE_PREAMBLE = "#include \"...\""; //$NON-NLS-1$ + private final static String DEFINE_PREAMBLE = "#define"; //$NON-NLS-1$ + private final static String COMMAND_ID_BEGIN = "begin generating scanner info for scd_cmd_"; //$NON-NLS-1$ + private final static String COMMAND_ID_END = "end generating scanner info for scd_cmd_"; //$NON-NLS-1$ + + private final static int NO_INCLUDES = 0; + private final static int QUOTE_INCLUDES = 1; + private final static int INCLUDES = 2; + + private IScannerInfoCollector fCollector = null; + + private int expectingIncludes = NO_INCLUDES; + private List symbols; + private List includes; + private List quoteIncludes; + private int commandId = -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) { + this.fCollector = collector; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#processLine(java.lang.String) + */ + public boolean processLine(String line) { + boolean rc = false; + TraceUtil.outputTrace("GCCPerFileSIPConsoleParser parsing line: [", line, "]"); //$NON-NLS-1$//$NON-NLS-2$ + + if (line.startsWith(COMMAND_ID_BEGIN)) { + commandId = Integer.parseInt(line.substring(COMMAND_ID_BEGIN.length())); + symbols = new ArrayList(); + includes = new ArrayList(); + quoteIncludes = new ArrayList(); + } + else if (line.startsWith(COMMAND_ID_END)) { + Map scannerInfo = new HashMap(); + scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, includes); + scannerInfo.put(ScannerInfoTypes.QUOTE_INCLUDE_PATHS, quoteIncludes); + scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); + fCollector.contributeToScannerConfig(new Integer(commandId), scannerInfo); + commandId = -1; + rc = true; + } + // contribution of -dD option + else if (line.startsWith(DEFINE_PREAMBLE)) { + String[] defineParts = line.split("\\s+", 3); //$NON-NLS-1$ + if (defineParts[0].equals(DEFINE_PREAMBLE)) { + String symbol = null; + switch (defineParts.length) { + case 2: + symbol = defineParts[1]; + break; + case 3: + symbol = defineParts[1] + "=" + defineParts[2]; //$NON-NLS-1$ + break; + } + if (symbol != null && !symbols.contains(symbol)) { + symbols.add(symbol); + } + } + } + // now get all the includes + else if (line.startsWith(QUOTE_INCLUDE_PREAMBLE) && line.endsWith("search starts here:")) { //$NON-NLS-1$ + expectingIncludes = QUOTE_INCLUDES; + } + else if (line.startsWith(INCLUDE_PREAMBLE) && line.endsWith("search starts here:")) { //$NON-NLS-1$ + expectingIncludes = INCLUDES; + } + else if (line.startsWith("End of search list.")) { //$NON-NLS-1$ + expectingIncludes = NO_INCLUDES; + } + else if (expectingIncludes == QUOTE_INCLUDES) { + if (!quoteIncludes.contains(line)) + quoteIncludes.add(line); + } + else if (expectingIncludes == INCLUDES) { + if (!includes.contains(line)) + includes.add(line); + } + + return rc; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#shutdown() + */ + public void shutdown() { +// Map scannerInfo = new HashMap(); +// scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, includes); +// scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); +// fCollector.contributeToScannerConfig(fProject, scannerInfo); +// TraceUtil.outputTrace("Scanner info from \'specs\' file", //$NON-NLS-1$ +// "Include paths", includes, new ArrayList(), "Defined symbols", symbols); //$NON-NLS-1$ //$NON-NLS-2$); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java new file mode 100644 index 00000000000..e111681cab3 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * GCC related utility class + * + * @author vhirsl + */ +public class GCCScannerConfigUtil { + public static final String CPP_SPECS_FILE = "specs.cpp"; //$NON-NLS-1$ + public static final String C_SPECS_FILE = "specs.c"; //$NON-NLS-1$ + + public static void createSpecs() { + IPath path = MakeCorePlugin.getWorkingDirectory(); + try { + createSpecsFile(path, CPP_SPECS_FILE); + createSpecsFile(path, C_SPECS_FILE); + } catch (CoreException e) { + MakeCorePlugin.log(e); + } + } + + private static void createSpecsFile(IPath path, String fileName) throws CoreException { + IPath specs = path.append(fileName); + File specsFile = specs.toFile(); + if (!specsFile.exists()) { + try { + FileOutputStream file = new FileOutputStream(specsFile); + file.write('\n'); + file.close(); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + MakeCorePlugin.getUniqueIdentifier(), -1, + MakeMessages.getString("GCCScannerConfigUtil.Error_Message"), e)); //$NON-NLS-1$ + } + } + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java new file mode 100644 index 00000000000..cba556e3673 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java @@ -0,0 +1,343 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.util.ArrayList; +import java.util.Arrays; +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.MakeMessages; +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 { + private final static String SINGLE_QUOTE_STRING = "\'"; //$NON-NLS-1$ + private final static String DOUBLE_QUOTE_STRING = "\""; //$NON-NLS-1$ + private final static char[] matchingChars = {'`', '\'', '\"'}; + + private String[] compilerInvocation; + + private ScannerInfoConsoleParserUtility fUtil = null; + + /* (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); + + // check additional compiler commands from extension point manifest + compilerInvocation = getCompilerCommands(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#getUtility() + */ + protected AbstractGCCBOPConsoleParserUtility getUtility() { + return fUtil; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.gnu.AbstractGCCBOPConsoleParser#processSingleLine(java.lang.String) + */ + protected boolean processSingleLine(String line) { + boolean rc = false; + // Known patterns: + // (a) gcc|g++ ... -Dxxx -Iyyy ... + List allTokens = tokenize(line); +// ArrayList allTokens = new ArrayList(Arrays.asList(line.split("\\s+")));//$NON-NLS-1$ + if (allTokens.size() <= 1) + return false; + Iterator I = allTokens.iterator(); + String token = ((String) I.next()).toLowerCase(); + + boolean found = false; + for (int i = 0; i < compilerInvocation.length; i++) { + if (token.indexOf(compilerInvocation[i]) != -1) { + found = true; + break; + } + } + if (found) { + // Recognized gcc or g++ compiler invocation + List includes = new ArrayList(); + List symbols = new ArrayList(); + List targetSpecificOptions = new ArrayList(); + + rc = true; + String fileName = null; + // discover all -I options + parseLineForIncludePaths(line, includes); + // discover all -D options + parseLineForSymbolDefinitions(line, symbols); + + while (I.hasNext()) { + token = (String) I.next(); + if (token.startsWith("-m") || //$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.startsWith(DOUBLE_QUOTE_STRING) && + possibleFileName.endsWith(DOUBLE_QUOTE_STRING)) || + (possibleFileName.startsWith(SINGLE_QUOTE_STRING) && + possibleFileName.endsWith(SINGLE_QUOTE_STRING))) { + possibleFileName = possibleFileName.substring(1, possibleFileName.length()-1).trim(); + } + 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(); + } + + IProject project = getProject(); + IFile file = null; + List translatedIncludes = includes; + if (includes.size() > 0) { + if (fileName != null) { + if (fUtil != null) { + file = fUtil.findFile(fileName); + if (file != null) { + project = file.getProject(); + translatedIncludes = fUtil.translateRelativePaths(file, fileName, includes); + } + } + } + else { + final String error = MakeMessages.getString("ConsoleParser.Filename_Missing_Error_Message"); //$NON-NLS-1$ + TraceUtil.outputError(error, line); + if (fUtil != null) { + fUtil.generateMarker(getProject(), -1, error + line, IMarkerGenerator.SEVERITY_WARNING, null); + } + } + if (file == null && fUtil != null) { // real world case + // remove include paths since there was no chance to translate them + translatedIncludes.clear(); + } + } + // Contribute discovered includes and symbols to the ScannerInfoCollector + if (translatedIncludes.size() > 0 || symbols.size() > 0) { + Map scannerInfo = new HashMap(); + 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 rc; + } + + /** + * @param line + * @return list of tokens + */ + private List tokenize(String line) { + List rv = new ArrayList(2); + // find special characters that need to be matched: `, ' and " + // First Matching Chararcter + int prevFmc = line.length(); + int emc = -1; + char matchingChar = 0; + for (int i = 0; i < matchingChars.length; ++i) { + char ch = matchingChars[i]; + int fmc = line.indexOf(ch); + if (fmc > -1 && fmc < prevFmc) { + emc = line.indexOf(ch, fmc+1); + if (emc > fmc) { + matchingChar = ch; + prevFmc = fmc; + } + } + } + if (matchingChar != 0) { // found matched chars + String prefix = line.substring(0, prevFmc).trim(); + rv.addAll(Arrays.asList(prefix.split("\\s+")));//$NON-NLS-1$ + + rv.add(line.substring(prevFmc, emc+1)); + + // recursion + rv.addAll(tokenize(line.substring(emc+1).trim())); + } + else { + rv.addAll(Arrays.asList(line.split("\\s+")));//$NON-NLS-1$ + } + return rv; + } + + /** + * @param line + * @param includes + */ + private void parseLineForIncludePaths(String line, List includes) { + final String fDashI = "-I"; //$NON-NLS-1$ + int prevIndex = 0; + for (int index = line.indexOf(fDashI, prevIndex); index != -1; + prevIndex = index+2, index = line.indexOf(fDashI, prevIndex)) { + String delimiter = "\\s+"; //$NON-NLS-1$ + if (line.charAt(index-1) == '\'' || line.charAt(index-1) == '\"') { + // look for only one more ' or " + delimiter = String.valueOf(line.charAt(index-1)); + } + String postfix = line.substring(index+2).trim(); + if (postfix.charAt(0) == '-') { // empty -I + continue; + } + if (postfix.startsWith(SINGLE_QUOTE_STRING) || postfix.startsWith(DOUBLE_QUOTE_STRING)) { + delimiter = postfix.substring(0, 1); + } + String[] tokens = postfix.split(delimiter); + int tokIndex = (tokens.length > 1 && tokens[0].length() == 0) ? 1 : 0; + String iPath = tokens[tokIndex]; + String temp = iPath; + // check for '\ ' + for (++tokIndex; (temp.endsWith("\\") && tokIndex < tokens.length && //$NON-NLS-1$ + tokens[tokIndex].length() > 0 && !tokens[tokIndex].startsWith("-")); //$NON-NLS-1$ + ++tokIndex) { + int beg = postfix.indexOf(temp)+temp.length(); + int end = postfix.indexOf(tokens[tokIndex])+tokens[tokIndex].length(); + iPath = iPath.substring(0, iPath.length()-1) + postfix.substring(beg, end); + temp += postfix.substring(beg, end); + } + String nPath = iPath; + if (fUtil != null) { + nPath = fUtil.normalizePath(iPath); + } + if (!includes.contains(nPath)) { + includes.add(nPath); + } + } + } + + /** + * @param line + * @param symbols + */ + private void parseLineForSymbolDefinitions(String line, List symbols) { + final String fDashD = "-D"; //$NON-NLS-1$ + int prevIndex = 0; + String delimiter = null; + String splitRegex = "\\s+"; //$NON-NLS-1$ + for (int index = line.indexOf(fDashD, prevIndex); index != -1; + prevIndex = index+2, index = line.indexOf(fDashD, prevIndex)) { + int nDelimiterSymbols = 2; + String postfix = line.substring(index+2).trim(); + if (postfix.charAt(0) == '-') { // empty -D + continue; + } + if (line.charAt(index-1) == '\'' || line.charAt(index-1) == '\"') { + // look for only one more ' or " + delimiter = String.valueOf(line.charAt(index-1)); + nDelimiterSymbols = 1; + } + else { + String[] tokens = postfix.split(splitRegex, 2); + if (tokens.length > 0 && tokens[0].length() > 0) { + int sQuoteIndex = tokens[0].indexOf(SINGLE_QUOTE_STRING); + int dQuoteIndex = tokens[0].indexOf(DOUBLE_QUOTE_STRING); + if (sQuoteIndex == -1 && dQuoteIndex == -1) { + // simple case, no quotes + if (!symbols.contains(tokens[0])) { + symbols.add(tokens[0]); + } + continue; + } + else { + delimiter = (sQuoteIndex != -1 && (dQuoteIndex == -1 || sQuoteIndex < dQuoteIndex)) ? SINGLE_QUOTE_STRING : DOUBLE_QUOTE_STRING; + } + } + else + continue; + } + + // find next matching delimiter + int nextDelimiterIndex = -1; + int prevDelimiterIndex = -1; + do { + nextDelimiterIndex = postfix.indexOf(delimiter, nextDelimiterIndex+1); + if (nextDelimiterIndex == 0 || (nextDelimiterIndex > 0 && postfix.charAt(nextDelimiterIndex-1) != '\\')) { + --nDelimiterSymbols; + if (nDelimiterSymbols > 0) { + prevDelimiterIndex = nextDelimiterIndex; + } + } + } + while (nDelimiterSymbols > 0 && nextDelimiterIndex != -1); + if (nDelimiterSymbols > 0) + continue; // non matching delimiter + + // take everything up to the last delimiter + boolean bStartsWithDelimiter = postfix.startsWith(delimiter); + String symbol = postfix.substring(bStartsWithDelimiter ? 1 : 0, nextDelimiterIndex); + if (!bStartsWithDelimiter) { + // there is still a delimiter to be removed + if (prevDelimiterIndex != -1) { + symbol = symbol.substring(0, prevDelimiterIndex) + symbol.substring(prevDelimiterIndex+1); + } + } + // transform '\"' into '"' + if (delimiter.equals(DOUBLE_QUOTE_STRING)) { + symbol = symbol.replaceAll("\\\\\"", DOUBLE_QUOTE_STRING); //$NON-NLS-1$ + } + if (!symbols.contains(symbol)) { + symbols.add(symbol); + } + } + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java new file mode 100644 index 00000000000..7e378667105 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.util.ArrayList; +import java.util.HashMap; +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.IScannerInfoConsoleParser; +import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; + +/** + * Parses output of gcc -c -v specs.c or + * g++ -c -v specs.cpp + * command + * + * @author vhirsl + */ +public class GCCSpecsConsoleParser implements IScannerInfoConsoleParser { + private final String INCLUDE = "#include"; //$NON-NLS-1$ + private final String DEFINE = "#define"; //$NON-NLS-1$ + + private IProject fProject = null; + private IScannerInfoCollector fCollector = null; + + private boolean expectingIncludes = false; + private List symbols = new ArrayList(); + private List includes = new ArrayList(); + + /* (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) { + this.fProject = project; + this.fCollector = collector; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#processLine(java.lang.String) + */ + public boolean processLine(String line) { + boolean rc = false; + TraceUtil.outputTrace("GCCSpecsConsoleParser parsing line: [", line, "]"); //$NON-NLS-1$ //$NON-NLS-2$ + + // contribution of -dD option + if (line.startsWith(DEFINE)) { + String[] defineParts = line.split("\\s+", 3); //$NON-NLS-1$ + if (defineParts[0].equals(DEFINE)) { + String symbol = null; + switch (defineParts.length) { + case 2: + symbol = defineParts[1]; + break; + case 3: + symbol = defineParts[1] + "=" + defineParts[2]; //$NON-NLS-1$ + break; + } + if (symbol != null && !symbols.contains(symbol)) { //$NON-NLS-1$ + symbols.add(symbol); + } + } + } + // now get all the includes + else if (line.startsWith(INCLUDE) && line.endsWith("search starts here:")) { //$NON-NLS-1$ + expectingIncludes = true; + } + else if (line.startsWith("End of search list.")) { //$NON-NLS-1$ + expectingIncludes = false; + } + else if (expectingIncludes) { + if (!includes.contains(line)) + includes.add(line); + } + + return rc; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#shutdown() + */ + public void shutdown() { + Map scannerInfo = new HashMap(); + scannerInfo.put(ScannerInfoTypes.INCLUDE_PATHS, includes); + scannerInfo.put(ScannerInfoTypes.SYMBOL_DEFINITIONS, symbols); + fCollector.contributeToScannerConfig(fProject, scannerInfo); + TraceUtil.outputTrace("Scanner info from \'specs\' file", //$NON-NLS-1$ + "Include paths", includes, new ArrayList(), "Defined symbols", symbols); //$NON-NLS-1$ //$NON-NLS-2$); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/ScannerInfoConsoleParserUtility.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/ScannerInfoConsoleParserUtility.java new file mode 100644 index 00000000000..2ee24b12b77 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/ScannerInfoConsoleParserUtility.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + * Tianchao Li (tianchao.li@gmail.com) - arbitrary build directory (bug #136136) + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.gnu; + +import java.io.File; +import java.io.IOException; +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.MakeCorePlugin; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Implements error reporting mechanism and file/path translation mechanism + * Taken from ErrorParserManager and modified. + * + * @author vhirsl + */ +public class ScannerInfoConsoleParserUtility extends AbstractGCCBOPConsoleParserUtility { + /* + * For tracking the location of files being compiled + */ + private Map fFilesInProject; + private List fCollectedFiles; + private List fNameConflicts; + + public ScannerInfoConsoleParserUtility(IProject project, IPath workingDirectory, IMarkerGenerator markerGenerator) { + super(project, workingDirectory, markerGenerator); + + fFilesInProject = new HashMap(); + fCollectedFiles = new ArrayList(); + fNameConflicts = new ArrayList(); + + collectFiles(getProject(), fCollectedFiles); + + for (int i = 0; i < fCollectedFiles.size(); i++) { + IFile curr = (IFile) fCollectedFiles.get(i); + Object existing = fFilesInProject.put(curr.getName(), curr); + if (existing != null) { + fNameConflicts.add(curr.getName()); + } + } + } + + /** + * Called by the console line parsers to find a file with a given name. + * @param fileName + * @return IFile or null + */ + public IFile findFile(String fileName) { + IFile file = findFilePath(fileName); + if (file == null) { + // Try the project's map. + file = findFileName(fileName); + if (file != null) { + // If there is a conflict then try all files in the project. + if (isConflictingName(fileName)) { + file = null; + + // Create a problem marker + final String error = MakeMessages.getString("ConsoleParser.Ambiguous_Filepath_Error_Message"); //$NON-NLS-1$ + TraceUtil.outputError(error, fileName); + generateMarker(getProject(), -1, error+fileName, IMarkerGenerator.SEVERITY_WARNING, null); + } + } + } + return file; + } + + /** + * @param filePath + * @return + */ + protected IFile findFilePath(String filePath) { + IPath path = null; + IPath fp = new Path(filePath); + if (fp.isAbsolute()) { + if (getBaseDirectory().isPrefixOf(fp)) { + int segments = getBaseDirectory().matchingFirstSegments(fp); + path = fp.removeFirstSegments(segments); + } else { + path = fp; + } + } else { + path = getWorkingDirectory().append(filePath); + } + + IFile file = null; + // The workspace may throw an IllegalArgumentException + // Catch it and the parser should fallback to scan the entire project. + try { + file = findFileInWorkspace(path); + } catch (Exception e) { + } + + // We have to do another try, on Windows for cases like "TEST.C" vs "test.c" + // We use the java.io.File canonical path. + if (file == null || !file.exists()) { + File f = path.toFile(); + try { + String canon = f.getCanonicalPath(); + path = new Path(canon); + file = findFileInWorkspace(path); + } catch (IOException e1) { + } + } + return (file != null && file.exists()) ? file : null; + } + + /** + * @param fileName + * @return + */ + protected IFile findFileName(String fileName) { + IPath path = new Path(fileName); + return (IFile) fFilesInProject.get(path.lastSegment()); + } + + protected IFile findFileInWorkspace(IPath path) { + IFile file = null; + if (path.isAbsolute()) { + IWorkspaceRoot root = getProject().getWorkspace().getRoot(); + file = root.getFileForLocation(path); + // It may be a link resource so we must check it also. + if (file == null) { + IFile[] files = root.findFilesForLocation(path); + for (int i = 0; i < files.length; i++) { + if (files[i].getProject().equals(getProject())) { + file = files[i]; + break; + } + } + } + + } else { + file = getProject().getFile(path); + } + return file; + } + + protected void collectFiles(IContainer parent, List result) { + try { + IResource[] resources = parent.members(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (resource instanceof IFile) { + result.add(resource); + } else if (resource instanceof IContainer) { + collectFiles((IContainer) resource, result); + } + } + } catch (CoreException e) { + MakeCorePlugin.log(e.getStatus()); + } + } + + protected boolean isConflictingName(String fileName) { + IPath path = new Path(fileName); + return fNameConflicts.contains(path.lastSegment()); + } + + public List translateRelativePaths(IFile file, String fileName, List includes) { + List translatedIncludes = new ArrayList(includes.size()); + for (Iterator i = includes.iterator(); i.hasNext(); ) { + String include = (String) i.next(); + IPath includePath = new Path(include); + if (!includePath.isAbsolute() && !includePath.isUNC()) { // do not translate UNC paths + // First try the current working directory + IPath cwd = getWorkingDirectory(); + if (!cwd.isAbsolute()) { + cwd = getBaseDirectory().append(cwd); + } + + IPath filePath = new Path(fileName); + if (!filePath.isAbsolute()) { + // check if the cwd is the right one + // appending fileName to cwd should yield file path + filePath = cwd.append(fileName); + } + if (!filePath.toString().equalsIgnoreCase(file.getLocation().toString())) { + // must be the cwd is wrong + // check if file name starts with ".." + if (fileName.startsWith("..")) { //$NON-NLS-1$ + // probably multiple choices for cwd, hopeless + final String error = MakeMessages.getString("ConsoleParser.Working_Directory_Error_Message"); //$NON-NLS-1$ + TraceUtil.outputError(error, fileName); //$NON-NLS-1$ + generateMarker(file, -1, error, IMarkerGenerator.SEVERITY_WARNING, fileName); + break; + } + else { + // remove common segments at the end + IPath tPath = new Path(fileName); + if (fileName.startsWith(".")) { //$NON-NLS-1$ + tPath = tPath.removeFirstSegments(1); + } + // get the file path from the file + filePath = file.getLocation(); + IPath lastFileSegment = filePath.removeFirstSegments(filePath.segmentCount() - tPath.segmentCount()); + if (lastFileSegment.matchingFirstSegments(tPath) == tPath.segmentCount()) { + cwd = filePath.removeLastSegments(tPath.segmentCount()); + } + } + } + + IPath candidatePath = cwd.append(includePath); + File dir = candidatePath.toFile(); + include = candidatePath.toString(); + if (!dir.exists()) { + final String error = MakeMessages.getString("ConsoleParser.Nonexistent_Include_Path_Error_Message"); //$NON-NLS-1$ + TraceUtil.outputError(error, include); +// generateMarker(file, -1, error+include, IMarkerGenerator.SEVERITY_WARNING, fileName); + } + } + // TODO VMIR for now add unresolved paths as well + translatedIncludes.add(include); + } + return translatedIncludes; + } + + public String normalizePath(String path) { + int column = path.indexOf(':'); + if (column > 0) { + char driveLetter = path.charAt(column - 1); + if (Character.isLowerCase(driveLetter)) { + StringBuffer sb = new StringBuffer(); + if (column - 1 > 0) { + sb.append(path.substring(0, column-1)); + } + sb.append(Character.toUpperCase(driveLetter)); + sb.append(path.substring(column)); + path = sb.toString(); + } + } + if (path.indexOf('.') == -1 || path.equals(".")) { //$NON-NLS-1$ + return (new Path(path)).toString(); // convert separators to '/' + } + // lose "./" segments since they confuse the Path normalization + StringBuffer buf = new StringBuffer(path); + int len = buf.length(); + StringBuffer newBuf = new StringBuffer(buf.length()); + int scp = 0; // starting copy point + int ssp = 0; // starting search point + int sdot; + boolean validPrefix; + while (ssp < len && (sdot = buf.indexOf(".", ssp)) != -1) { //$NON-NLS-1$ + validPrefix = false; + int ddot = buf.indexOf("..", ssp);//$NON-NLS-1$ + if (sdot < ddot || ddot == -1) { + newBuf.append(buf.substring(scp, sdot)); + scp = sdot; + ssp = sdot + 1; + if (ssp < len) { + if (sdot == 0 || buf.charAt(sdot - 1) == '/' || buf.charAt(sdot - 1) == '\\') { + validPrefix = true; + } + char nextChar = buf.charAt(ssp); + if (validPrefix && nextChar == '/') { + ++ssp; + scp = ssp; + } + else if (validPrefix && nextChar == '\\') { + ++ssp; + if (ssp < len - 1 && buf.charAt(ssp) == '\\') { + ++ssp; + } + scp = ssp; + } + else { + // no path delimiter, must be '.' inside the path + scp = ssp - 1; + } + } + } + else if (sdot == ddot) { + ssp = sdot + 2; + } + } + newBuf.append(buf.substring(scp, len)); + + IPath orgPath = new Path(newBuf.toString()); + return orgPath.toString(); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/BuildOutputReaderJob.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/BuildOutputReaderJob.java new file mode 100644 index 00000000000..bdef3d51512 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/BuildOutputReaderJob.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.jobs; + +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; + +/** + * Build output reader job + * + * @author vhirsl + */ +public class BuildOutputReaderJob extends Job { + private static final String JOB_NAME = "Build Output Reader"; //$NON-NLS-1$ + + private IResource resource; + private InfoContext context; + private IScannerConfigBuilderInfo2 buildInfo; + + /** + * @param project + * @param buildInfo + */ + public BuildOutputReaderJob(IProject project, IScannerConfigBuilderInfo2 buildInfo) { + this(project, new InfoContext(project), buildInfo); + } + + public BuildOutputReaderJob(IProject project, InfoContext context, IScannerConfigBuilderInfo2 buildInfo) { + super(JOB_NAME); + this.resource = project; + this.context = context; + this.buildInfo = buildInfo; + setUser(true); + } + + /* (non-Javadoc) + * @see org.eclipse.core.internal.jobs.InternalJob#run(org.eclipse.core.runtime.IProgressMonitor) + */ + protected IStatus run(IProgressMonitor monitor) { + IProject project = resource.getProject(); + monitor.beginTask(MakeMessages.getString("ScannerConfigBuilder.Invoking_Builder"), 100); //$NON-NLS-1$ + monitor.subTask(MakeMessages.getString("ScannerConfigBuilder.Invoking_Builder") + //$NON-NLS-1$ + project.getName()); + + boolean rc = SCJobsUtil.readBuildOutputFile(project, buildInfo, new SubProgressMonitor(monitor, 70)); + rc |= SCJobsUtil.getProviderScannerInfo(project, context, buildInfo, new SubProgressMonitor(monitor, 20)); + if (rc) { + rc = SCJobsUtil.updateScannerConfiguration(project, context, buildInfo, new SubProgressMonitor(monitor, 10)); + } + + monitor.done(); + return (rc == true) ? Status.OK_STATUS : Status.CANCEL_STATUS; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/SCJobsUtil.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/SCJobsUtil.java new file mode 100644 index 00000000000..1b9785b123d --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/jobs/SCJobsUtil.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.jobs; + +import java.util.List; + +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.scannerconfig.IExternalScannerInfoProvider; +import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo2; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.internal.core.scannerconfig2.SCProfileInstance; +import org.eclipse.cdt.make.internal.core.scannerconfig2.ScannerConfigProfileManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; + +/** + * Utility class for build and job related functionality + * + * @author vhirsl + */ +public class SCJobsUtil { + private static class RC { + public RC(boolean init) { + rc = init; + } + /** + * @return Returns the rc. + */ + public boolean get() { + return rc; + } + /** + * @param rc The rc to set. + */ + public void set(boolean rc) { + this.rc = rc; + } + + public String toString() { + return rc ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$ + } + private boolean rc; + } + /** + * Call ESI providers to get scanner info + * + * @param collector + * @param buildInfo + * @param monitor + */ + public static boolean getProviderScannerInfo(final IProject project, + final IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + return getProviderScannerInfo(project, new InfoContext(project), buildInfo, monitor); + } + + public static boolean getProviderScannerInfo(final IProject project, + final InfoContext context, + final IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + + final RC rc = new RC(false); + // get the collector + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(project, context, buildInfo.getSelectedProfileId()); + final IScannerInfoCollector collector = profileInstance.getScannerInfoCollector(); + + List providerIds = buildInfo.getProviderIdList(); + for (int i = 0; i < providerIds.size(); ++i) { + final String providerId = (String) providerIds.get(i); + if (buildInfo.isProviderOutputParserEnabled(providerId)) { + final IExternalScannerInfoProvider esiProvider = profileInstance. + createExternalScannerInfoProvider(providerId); + if (esiProvider != null) { + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() { + esiProvider.invokeProvider(monitor, project, providerId, buildInfo, collector); + rc.set(true); + } + + public void handleException(Throwable exception) { + rc.set(false); + MakeCorePlugin.log(exception); + } + + }; + Platform.run(runnable); + } + } + } + return rc.get(); + } + + /** + * Update and persist scanner configuration + * + * @param project + * @param buildInfo + * @param monitor + */ + public static boolean updateScannerConfiguration(IProject project, + IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + return updateScannerConfiguration(project, new InfoContext(project), buildInfo, monitor); + } + + /** + * Update and persist scanner configuration + * + * @param project + * @param buildInfo + * @param monitor + */ + public static boolean updateScannerConfiguration(IProject project, + InfoContext context, + IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + final RC rc = new RC(false); + // get the collector + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(project, context, buildInfo.getSelectedProfileId()); + IScannerInfoCollector collector = profileInstance.getScannerInfoCollector(); + if (collector instanceof IScannerInfoCollector2) { + final IScannerInfoCollector2 collector2 = (IScannerInfoCollector2) collector; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() throws Exception { + collector2.updateScannerConfiguration(monitor); + rc.set(true); + } + + public void handleException(Throwable exception) { + rc.set(false); + MakeCorePlugin.log(exception); + } + + }; + Platform.run(runnable); + } + + return rc.get(); + } + + /** + * @param project + * @param buildInfo + * @param monitor + * @return + */ + public static boolean readBuildOutputFile(final IProject project, + final IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + return readBuildOutputFile(project, new InfoContext(project), buildInfo, monitor); + } + + /** + * @param project + * @param buildInfo + * @param monitor + * @return + */ + public static boolean readBuildOutputFile(final IProject project, + final InfoContext context, + final IScannerConfigBuilderInfo2 buildInfo, + final IProgressMonitor monitor) { + final RC rc = new RC(false); + // get the collector + SCProfileInstance profileInstance = ScannerConfigProfileManager.getInstance(). + getSCProfileInstance(project, context, buildInfo.getSelectedProfileId()); + final IScannerInfoCollector collector = profileInstance.getScannerInfoCollector(); + final IExternalScannerInfoProvider esiProvider = profileInstance. + createBuildOutputProvider(); + + if (buildInfo.isBuildOutputFileActionEnabled()) { + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() { + esiProvider.invokeProvider(monitor, project, null, buildInfo, collector); + rc.set(true); + } + + public void handleException(Throwable exception) { + rc.set(false); + MakeCorePlugin.log(exception); + } + + }; + Platform.run(runnable); + } + + return rc.get(); + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java new file mode 100644 index 00000000000..ecc6439f43b --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CCommandDSC.java @@ -0,0 +1,312 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Class that represents a compiler command and related scanner configuration + * + * @author vhirsl + */ +public class CCommandDSC { + private final static String SINGLE_SPACE = " "; //$NON-NLS-1$ + private final static String CMD_DESCRIPTION_ELEM = "commandDescription"; //$NON-NLS-1$ + private final static String CMD_SI_ELEM = "commandScannerInfo"; //$NON-NLS-1$ + private final static String OPTION_ELEM = "option"; //$NON-NLS-1$ + private final static String SI_ITEM_ELEM = "siItem"; //$NON-NLS-1$ + private final static String KEY_ATTR = "key"; //$NON-NLS-1$ + private final static String VALUE_ATTR = "value"; //$NON-NLS-1$ + private final static String QUOTE_INCLUDE_ATTR = "quote"; //$NON-NLS-1$ + private final static String KIND_ATTR = "kind"; //$NON-NLS-1$ + + private int commandId; + private List compilerCommand; // members are KVStringPair objects + private boolean discovered; + private boolean cppFileType; // C or C++ file type + + private List symbols; + private List includes; + private List quoteIncludes; + + /** + * @param cppFileType2 + */ + public CCommandDSC(boolean cppFileType) { + compilerCommand = new ArrayList(); + discovered = false; + this.cppFileType = cppFileType; + + symbols = new ArrayList(); + includes = new ArrayList(); + quoteIncludes = new ArrayList(); + } + + public boolean appliesToCPPFileType() { + return cppFileType; + } + + public void addSCOption(KVStringPair option) { + compilerCommand.add(option); + } + + /** + * @return + */ + public Integer getCommandIdAsInteger() { + return new Integer(getCommandId()); + } + /** + * @return Returns the commandId. + */ + public int getCommandId() { + return commandId; + } + /** + * @param commandId The commandId to set. + */ + public void setCommandId(int commandId) { + this.commandId = commandId; + } + + public String toString() { + String commandAsString = new String(); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)i.next(); + commandAsString += optionPair.getKey() + SINGLE_SPACE + + optionPair.getValue() + SINGLE_SPACE; + } + return commandAsString.trim(); + } + + public int getId() { + return commandId; + } + + /** + * Returns a command where -imacros and -include options have been removed + * @return + */ + public String getSCDRunnableCommand(boolean quoteIncludePaths) { + String commandAsString = new String(); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)i.next(); + if (optionPair.getKey().equals(SCDOptionsEnum.COMMAND.toString())) { + commandAsString += optionPair.getValue() + SINGLE_SPACE; + } + else { + // skip -include and -imacros options + if (optionPair.getKey().equals(SCDOptionsEnum.IMACROS_FILE.toString()) || + optionPair.getKey().equals(SCDOptionsEnum.INCLUDE_FILE.toString())) + continue; + if (quoteIncludePaths) { + if (optionPair.getKey().equals(SCDOptionsEnum.INCLUDE.toString())) { + commandAsString += optionPair.getKey() + SINGLE_SPACE + + "\"" + optionPair.getValue() + "\"" + SINGLE_SPACE; //$NON-NLS-1$//$NON-NLS-2$ + } + } + else { + commandAsString += optionPair.getKey() + SINGLE_SPACE + + optionPair.getValue() + SINGLE_SPACE; + } + } + } + return commandAsString.trim(); + } + + /** + * @return list of strings + */ + public List getImacrosFile() { + List imacrosFiles = new ArrayList(); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)i.next(); + if (optionPair.getKey().equals(SCDOptionsEnum.IMACROS_FILE.toString())) { + imacrosFiles.add(optionPair.getValue()); + } + } + return imacrosFiles; + } + + /** + * @return list of strings + */ + public List getIncludeFile() { + List includeFiles = new ArrayList(); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + KVStringPair optionPair = (KVStringPair)i.next(); + if (optionPair.getKey().equals(SCDOptionsEnum.INCLUDE_FILE.toString())) { + includeFiles.add(optionPair.getValue()); + } + } + return includeFiles; + } + +// public List getFilesList() { +// return files; +// } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object arg0) { + if (arg0 != null && arg0.getClass().equals(this.getClass())) { + CCommandDSC other = (CCommandDSC)arg0; + return (compilerCommand.equals(other.compilerCommand) && + cppFileType == other.cppFileType); + } + return false; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return compilerCommand.hashCode(); + } + + /** + * @return Returns the includes as strings. + */ + public List getIncludes() { + return includes; + } + /** + * @param includes The includes to set. + */ + public void setIncludes(List includes) { + this.includes = includes; + } + /** + * @return Returns the quote include paths as strings (for #include "...") + */ + public List getQuoteIncludes() { + return quoteIncludes; + } + /** + * @param includes. Quote include paths (for #include "...") + */ + public void setQuoteIncludes(List includes) { + quoteIncludes = includes; + } + /** + * @return Returns the symbols. + */ + public List getSymbols() { + return symbols; + } + /** + * @param symbols The symbols to set. + */ + public void setSymbols(List symbols) { + this.symbols = symbols; + } + /** + * @return Returns the discovered. + */ + public boolean isDiscovered() { + return discovered; + } + /** + * @param discovered The discovered to set. + */ + public void setDiscovered(boolean discovered) { + this.discovered = discovered; + } + + /** + * @param cmdElem + */ + public void serialize(Element cmdElem) { + Document doc = cmdElem.getOwnerDocument(); + // serialize the command + Element cmdDescElem = doc.createElement(CMD_DESCRIPTION_ELEM); + for (Iterator i = compilerCommand.iterator(); i.hasNext(); ) { + Element optionElem = doc.createElement(OPTION_ELEM); + KVStringPair option = (KVStringPair) i.next(); + optionElem.setAttribute(KEY_ATTR, option.getKey()); + optionElem.setAttribute(VALUE_ATTR, option.getValue()); + cmdDescElem.appendChild(optionElem); + } + cmdElem.appendChild(cmdDescElem); + // serialize includes and symbols + Element siElem = doc.createElement(CMD_SI_ELEM); + for (Iterator j = quoteIncludes.iterator(); j.hasNext(); ) { + Element siItem = doc.createElement(SI_ITEM_ELEM); + siItem.setAttribute(KIND_ATTR, "INCLUDE_PATH"); //$NON-NLS-1$ + siItem.setAttribute(VALUE_ATTR, (String) j.next()); + siItem.setAttribute(QUOTE_INCLUDE_ATTR, "true"); //$NON-NLS-1$ + siElem.appendChild(siItem); + } + for (Iterator j = includes.iterator(); j.hasNext(); ) { + Element siItem = doc.createElement(SI_ITEM_ELEM); + siItem.setAttribute(KIND_ATTR, "INCLUDE_PATH"); //$NON-NLS-1$ + siItem.setAttribute(VALUE_ATTR, (String) j.next()); + siElem.appendChild(siItem); + } + for (Iterator j = symbols.iterator(); j.hasNext(); ) { + Element siItem = doc.createElement(SI_ITEM_ELEM); + siItem.setAttribute(KIND_ATTR, "SYMBOL_DEFINITION"); //$NON-NLS-1$ + siItem.setAttribute(VALUE_ATTR, (String) j.next()); + siElem.appendChild(siItem); + } + cmdElem.appendChild(siElem); + } + + /** + * @param cmdElem + */ + public void deserialize(Element cmdElem) { + // read command options + NodeList descList = cmdElem.getElementsByTagName(CMD_DESCRIPTION_ELEM); + if (descList.getLength() > 0) { + Element descElem = (Element) descList.item(0); + NodeList optionList = descElem.getElementsByTagName(OPTION_ELEM); + for (int i = 0; i < optionList.getLength(); ++i) { + Element optionElem = (Element) optionList.item(i); + String key = optionElem.getAttribute(KEY_ATTR); + String value = optionElem.getAttribute(VALUE_ATTR); + KVStringPair option = new KVStringPair(key, value); + addSCOption(option); + } + } + // read associated scanner info + NodeList siList = cmdElem.getElementsByTagName(CMD_SI_ELEM); + if (siList.getLength() > 0) { + Element siElem = (Element) siList.item(0); + NodeList siItemList = siElem.getElementsByTagName(SI_ITEM_ELEM); + for (int i = 0; i < siItemList.getLength(); ++i) { + Element siItemElem = (Element) siItemList.item(i); + String kind = siItemElem.getAttribute(KIND_ATTR); + String value = siItemElem.getAttribute(VALUE_ATTR); + String quote = siItemElem.getAttribute(QUOTE_INCLUDE_ATTR); + if (kind.equals("INCLUDE_PATH")) { //$NON-NLS-1$ + if (quote.equals("true")) { //$NON-NLS-1$ + quoteIncludes.add(value); + } + else { + includes.add(value); + } + } + else if (kind.equals("SYMBOL_DEFINITION")) { //$NON-NLS-1$ + symbols.add(value); + } + } + setDiscovered(true); + } + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java new file mode 100644 index 00000000000..281de5f4dac --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.ICExtensionReference; +import org.eclipse.cdt.core.IMarkerGenerator; +import org.eclipse.cdt.make.internal.core.MakeMessages; +import org.eclipse.cdt.make.internal.core.scannerconfig2.SCMarkerGenerator; +import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.utils.ICygwinToolsFactroy; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; + +/** + * Use binary parser's 'cygpath' command to translate cygpaths to absolute paths. + * + * @author vhirsl + */ +public class CygpathTranslator { + private static final String CYGPATH_ERROR_MESSAGE = "CygpathTranslator.NotAvailableErrorMessage"; //$NON-NLS-1$ + private CygPath cygPath = null; + private boolean isAvailable = false; + + public CygpathTranslator(IProject project) { + SCMarkerGenerator scMarkerGenerator = new SCMarkerGenerator(); + try { + ICExtensionReference[] parserRef = CCorePlugin.getDefault().getBinaryParserExtensions(project); + for (int i = 0; i < parserRef.length; i++) { + try { + IBinaryParser parser = (IBinaryParser)parserRef[i].createExtension(); + ICygwinToolsFactroy cygwinToolFactory = (ICygwinToolsFactroy) parser.getAdapter(ICygwinToolsFactroy.class); + if (cygwinToolFactory != null) { + cygPath = cygwinToolFactory.getCygPath(); + if (cygPath != null) { + isAvailable = true; + break; + } + } + } catch (ClassCastException e) { + } + } + // No CygPath specified in BinaryParser page or not supported. + // Hoping that cygpath is on the path. + if (cygPath == null && Platform.getOS().equals(Platform.OS_WIN32)) { + cygPath = new CygPath("cygpath"); //$NON-NLS-1$ + isAvailable = true; + } + } + catch (CoreException e) { + } + catch (IOException e) { + isAvailable = false; + scMarkerGenerator = new SCMarkerGenerator(); + scMarkerGenerator.addMarker(project, -1, + MakeMessages.getString(CYGPATH_ERROR_MESSAGE), + IMarkerGenerator.SEVERITY_WARNING, null); + } + if (isAvailable) { + // remove problem markers + scMarkerGenerator.removeMarker(project, -1, + MakeMessages.getString(CYGPATH_ERROR_MESSAGE), + IMarkerGenerator.SEVERITY_WARNING, null); + } + } + + /** + * @param sumIncludes + * @return + */ + public static List translateIncludePaths(IProject project, List sumIncludes) { + // first check if cygpath translation is needed at all + boolean translationNeeded = false; + if (Platform.getOS().equals(Platform.OS_WIN32)) { + for (Iterator i = sumIncludes.iterator(); i.hasNext(); ) { + String include = (String) i.next(); + if (include.startsWith("/")) { //$NON-NLS-1$ + translationNeeded = true; + break; + } + } + } + if (!translationNeeded) { + return sumIncludes; + } + + CygpathTranslator cygpath = new CygpathTranslator(project); + if (cygpath.cygPath == null) return sumIncludes; + + List translatedIncludePaths = new ArrayList(); + for (Iterator i = sumIncludes.iterator(); i.hasNext(); ) { + String includePath = (String) i.next(); + IPath realPath = new Path(includePath); + if (realPath.toFile().exists()) { + translatedIncludePaths.add(includePath); + } + else { + String translatedPath = includePath; + if (cygpath.isAvailable) { + try { + translatedPath = cygpath.cygPath.getFileName(includePath); + } + catch (IOException e) { + TraceUtil.outputError("CygpathTranslator unable to translate path: ", includePath); //$NON-NLS-1$ + } + } + if (!translatedPath.equals(includePath)) { + // Check if the translated path exists + IPath transPath = new Path(translatedPath); + if (transPath.toFile().exists()) { + translatedIncludePaths.add(transPath.toPortableString()); + } + else { + // TODO VMIR for now add even if it does not exist + translatedIncludePaths.add(translatedPath); + } + } + else { + // TODO VMIR for now add even if it does not exist + translatedIncludePaths.add(translatedPath); + } + } + } + cygpath.cygPath.dispose(); + return translatedIncludePaths; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVList.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVList.java new file mode 100644 index 00000000000..26f45e381cf --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVList.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * Key - Value (List) pair + * + * @author vhirsl + */ +public class KVList { + String key; + List value; + + public KVList(String key) { + this.key = key; + this.value = new ArrayList(); + } + + /** + * List must not be <code>null</code>. + */ + public KVList(String key, List value) { + this.key = key; + this.value = value; + } + + String getKey() { + return key; + } + + List getValue() { + return value; + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVStringPair.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVStringPair.java new file mode 100644 index 00000000000..4df20b5d79e --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/KVStringPair.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +/** + * Key - Value String Pair + * + * @author vhirsl + */ +public class KVStringPair { + private String key; + private String value; + + /** + * + */ + public KVStringPair(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object arg0) { + if (arg0 != null && arg0.getClass().equals(this.getClass())) { + KVStringPair arg = (KVStringPair) arg0; + return (key.equals(arg.getKey()) && value.equals(arg.getValue())); + } + return false; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return 17 * key.hashCode() + value.hashCode(); + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return key + " -> " + value; //$NON-NLS-1$ + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/LogWriter.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/LogWriter.java new file mode 100644 index 00000000000..74eef6af315 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/LogWriter.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; + +/** + * Log writer utility + * + * @author vhirsl + */ +public class LogWriter { + protected File logFile = null; + protected Writer log = null; + protected boolean newSession = true; + + protected static final String SESSION = "*** SESSION";//$NON-NLS-1$ + protected static final String ENTRY = "ENTRY";//$NON-NLS-1$ + protected static final String SUBENTRY = "SUBENTRY";//$NON-NLS-1$ + protected static final String MESSAGE = "MESSAGE";//$NON-NLS-1$ + protected static final String STACK = "STACK";//$NON-NLS-1$ + + protected static final String LINE_SEPARATOR; + protected static final String TAB_STRING = "\t";//$NON-NLS-1$ + protected static final long MAXLOG_SIZE = 10000000; + static { + String s = System.getProperty("line.separator");//$NON-NLS-1$ + LINE_SEPARATOR = s == null ? "\n" : s;//$NON-NLS-1$ + } + + /** + * + */ + public LogWriter(File log) { + this.logFile = log; + if(log.length() > MAXLOG_SIZE){ + log.delete(); + } + openLogFile(); + } + + protected void closeLogFile() throws IOException { + try { + if (log != null) { + log.flush(); + log.close(); + } + } finally { + log = null; + } + } + + protected void openLogFile() { + try { + log = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logFile.getAbsolutePath(), true), "UTF-8"));//$NON-NLS-1$ + if (newSession) { + writeHeader(); + newSession = false; + } + } catch (IOException e) { + // there was a problem opening the log file so log to the console + //log = logForStream(System.err); + } + } + protected void writeHeader() throws IOException { + writeln(); + write(SESSION); + writeSpace(); + String date = getDate(); + write(date); + writeSpace(); + for (int i=SESSION.length()+date.length(); i<78; i++) { + write("-");//$NON-NLS-1$ + } + writeln(); + } + + protected String getDate() { + try { + DateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$ + return formatter.format(new Date()); + } catch (Exception e) { + // If there were problems writing out the date, ignore and + // continue since that shouldn't stop us from losing the rest + // of the information + } + return Long.toString(System.currentTimeMillis()); + } + + /** + * Writes the given string to the log, followed by the line terminator string. + */ + public void writeln(String s) throws IOException { + write(s); + writeln(); + } + /** + * Shuts down the log. + */ + public synchronized void shutdown() { + try { + if (logFile != null) { + closeLogFile(); + logFile = null; + } else { + if (log != null) { + Writer old = log; + log = null; + old.flush(); + old.close(); + } + } + } catch (Exception e) { + //we've shutdown the log, so not much else we can do! + e.printStackTrace(); + } + } + + protected void write(Throwable throwable) throws IOException { + if (throwable == null) + return; + write(STACK); + writeSpace(); + boolean isCoreException = throwable instanceof CoreException; + if (isCoreException) + writeln("1");//$NON-NLS-1$ + else + writeln("0");//$NON-NLS-1$ + throwable.printStackTrace(new PrintWriter(log)); + if (isCoreException) { + CoreException e = (CoreException) throwable; + write(e.getStatus(), 0); + } + } + + public synchronized void log(IStatus status){ + try { + this.write(status, 0); + } catch (IOException e) { + } + } + protected void write(IStatus status, int depth) throws IOException { + if (depth == 0) { + write(ENTRY); + } else { + write(SUBENTRY); + writeSpace(); + write(Integer.toString(depth)); + } + writeSpace(); + write(status.getPlugin()); + writeSpace(); + write(Integer.toString(status.getSeverity())); + writeSpace(); + write(Integer.toString(status.getCode())); + writeSpace(); + write(getDate()); + writeln(); + + write(MESSAGE); + writeSpace(); + writeln(status.getMessage()); + + //Took out the stack dump - too much space + //write(status.getException()); + + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) { + write(children[i], depth+1); + } + } + } + + protected void writeln() throws IOException { + write(LINE_SEPARATOR); + } + protected void write(String message) throws IOException { + if (message != null) + log.write(message); + } + protected void writeSpace() throws IOException { + write(" ");//$NON-NLS-1$ + } + + public synchronized void flushLog(){ + try { + log.flush(); + } catch (IOException e) {} + } + + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SCDOptionsEnum.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SCDOptionsEnum.java new file mode 100644 index 00000000000..376efa68ef3 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SCDOptionsEnum.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +/** + * Enumeration class for scanner configuration affecting command line options + * + * @author vhirsl + */ +public final class SCDOptionsEnum { + + public static final SCDOptionsEnum COMMAND = new SCDOptionsEnum(0); // gcc or similar command + public static final int MIN = 1; + public static final SCDOptionsEnum DEFINE = new SCDOptionsEnum(1); // -D name + public static final SCDOptionsEnum UNDEFINE = new SCDOptionsEnum(2); // -U name + public static final SCDOptionsEnum IDASH = new SCDOptionsEnum(3); // -I- + public static final SCDOptionsEnum INCLUDE = new SCDOptionsEnum(4); // -I dir + public static final SCDOptionsEnum NOSTDINC = new SCDOptionsEnum(5); // -nostdinc + public static final SCDOptionsEnum NOSTDINCPP = new SCDOptionsEnum(6); // -nostdinc++ + public static final SCDOptionsEnum INCLUDE_FILE = new SCDOptionsEnum(7); // -include file + public static final SCDOptionsEnum IMACROS_FILE = new SCDOptionsEnum(8); // -imacros file + public static final SCDOptionsEnum IDIRAFTER = new SCDOptionsEnum(9); // -idirafter dir + public static final SCDOptionsEnum ISYSTEM = new SCDOptionsEnum(10); // -isystem dir + public static final SCDOptionsEnum IPREFIX = new SCDOptionsEnum(11); // -iprefix prefix + public static final SCDOptionsEnum IWITHPREFIX = new SCDOptionsEnum(12); // -iwithprefix dir + public static final SCDOptionsEnum IWITHPREFIXBEFORE = new SCDOptionsEnum(13); // -iwithprefixbefore dir + public static final int MAX = 13; + + private static final String[] SCDOPTION_STRING_VALS = { + "cc", //$NON-NLS-1$ + "-D", //$NON-NLS-1$ + "-U", //$NON-NLS-1$ + "-I-", //$NON-NLS-1$ + "-I", //$NON-NLS-1$ + "-nostdinc", //$NON-NLS-1$ + "-nostdinc++", //$NON-NLS-1$ + "-include", //$NON-NLS-1$ + "-imacros", //$NON-NLS-1$ + "-idirafter", //$NON-NLS-1$ + "-isystem", //$NON-NLS-1$ + "-iprefix", //$NON-NLS-1$ + "-iwithprefix", //$NON-NLS-1$ + "-iwithprefixbefore" //$NON-NLS-1$ + }; + private static final SCDOptionsEnum SCDOPTIONS[] = { + COMMAND, DEFINE, UNDEFINE, IDASH, INCLUDE, NOSTDINC, NOSTDINCPP, INCLUDE_FILE, IMACROS_FILE, + IDIRAFTER, ISYSTEM, IPREFIX, IWITHPREFIX, IWITHPREFIXBEFORE + }; + + /** + * + */ + private SCDOptionsEnum(int val) { + this._enum = val; + } + + public int getEnumValue() { + return _enum; + } + + public static SCDOptionsEnum getSCDOptionsEnum(int val) { + if (val >= 0 && val <= MAX) { + return SCDOPTIONS[val]; + } + return null; + } + + public static SCDOptionsEnum getSCDOptionsEnum(String desc) { + for (int i = 0; i <= MAX; ++i) { + if (desc.equals(SCDOPTION_STRING_VALS[i])) { + return SCDOPTIONS[i]; + } + } + return null; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object arg0) { + if (arg0 == null) return false; + if (arg0 == this) return true; + if (arg0 instanceof SCDOptionsEnum) return (_enum == ((SCDOptionsEnum)arg0)._enum); + return false; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _enum*17 + 11; + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return SCDOPTION_STRING_VALS[_enum]; + } + + private final int _enum; +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java new file mode 100644 index 00000000000..0066722a245 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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 + *******************************************************************************/ + +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + + +/** + * Represents a symbol definition with possible multiple values + * example: + * LOG_LEVEL + * LOG_LEVEL = 2 + * LOG_LEVEL = LOG_BASE + 1 + * @author vhirsl + */ +public class SymbolEntry { + private static final String UNSPECIFIED_VALUE = "1"; //$NON-NLS-1$ + private String name; + private Map values; // Values can be either in the active (selected) group or in the removed group + +// public SymbolEntry(String name) { +// this.name = name; +// } + + public SymbolEntry(String name, String value) { + this(name, value, true); + } + public SymbolEntry(String name, String value, boolean active) { + this.name = name; + if (values == null) { + values = new LinkedHashMap(1); + } + values.put(value, Boolean.valueOf(active)); + } + public SymbolEntry(SymbolEntry se) { + name = se.name; + // deep copy + values = new LinkedHashMap(se.values.size()); + for (Iterator i = se.values.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + Boolean value = (Boolean) se.values.get(key); + values.put(key, Boolean.valueOf(value.booleanValue())); + } + } + + public boolean add(String value) { + return add(value, true); + } + public boolean add(String value, boolean active) { + boolean rc = false; + if (!values.containsKey(value)) { + values.put(value, Boolean.valueOf(active)); + rc = true; + } + return rc; + } + public void replace(String value, boolean active) { + values.put(value, Boolean.valueOf(active)); + } + +// private void addAll(SymbolEntry se) { +// values.putAll(se.values); +// } + + public void remove(String value) { + values.remove(value); + } + public void removeAll() { + values = null; + } + + public List getActive() { + return get(true, true, true); + } + public List getActiveRaw() { + return get(false, true, true); + } + + public List getRemoved() { + return get(true, true, false); + } + public List getRemovedRaw() { + return get(false, true, false); + } + + public List getAll() { + return get(true, false, true /*don't care*/); + } + public List getAllRaw() { + return get(false, false, true /*don't care*/); + } + + /** + * Utility function to retrieve values as a set. + * + * @param format - false = raw + * @param subset - false = all + * @param active - false = removed + * @return List + */ + private List get(boolean format, boolean subset, boolean active) { + List rv = new ArrayList(values.size()); + for (Iterator i = values.keySet().iterator(); i.hasNext(); ) { + String val = (String) i.next(); + if (subset && ((Boolean) values.get(val)).booleanValue() != active) + continue; + if (format) { + rv.add(name + "=" + (val == null ? UNSPECIFIED_VALUE : val));//$NON-NLS-1$ + } + else { + rv.add(name + (val == null ? "" : "=" + val));//$NON-NLS-1$ //$NON-NLS-2$ + } + } + return rv; + } + /** + * Returns only value part of all active entries + * @return List + */ + public List getValuesOnly(boolean active) { + List rv = new ArrayList(values.size()); + for (Iterator i = values.keySet().iterator(); i.hasNext(); ) { + String val = (String) i.next(); + if (((Boolean) values.get(val)).booleanValue() == active) { + rv.add(val == null ? UNSPECIFIED_VALUE : val); + } + } + return rv; + } + + public int numberOfValues() { + return values.size(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(name); + buffer.append(':'); + for (Iterator i = values.keySet().iterator(); i.hasNext(); ) { + String val = (String) i.next(); + buffer.append('\t'); + buffer.append((val == null) ? "null" : val);//$NON-NLS-1$ + if (((Boolean) values.get(val)).booleanValue() == true) { + buffer.append("(active)");//$NON-NLS-1$ + } + buffer.append('\n'); + } + return buffer.toString(); + } +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java new file mode 100644 index 00000000000..0d04dc0c86b --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/TraceUtil.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 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 + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.scannerconfig.util; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.make.core.MakeCorePlugin; + +/** + * Tracebility related utility functions + * + * @author vhirsl + */ +public class TraceUtil { + public static final String EOL = System.getProperty("line.separator"); //$NON-NLS-1$ + public static boolean SCANNER_CONFIG = false; + private static LogWriter logger = null; + + static { + logger = new LogWriter(MakeCorePlugin.getDefault().getStateLocation().append(".log").toFile()); //$NON-NLS-1$ + } + /* (non-Javadoc) + * @see java.lang.Object#finalize() + */ + protected void finalize() throws Throwable { + logger.shutdown(); + super.finalize(); + } + + public static boolean isTracing() { + return SCANNER_CONFIG; + } + + public static void outputTrace(String prefix, String msg, String postfix) { + if (isTracing()) { + //System.out.println(); + System.out.println(prefix + ' ' + msg + ' ' + postfix); + } + } + + /** + * For traces of type: + * Title: + * Subtitle1: + * item1[0] + * item1[1] + * ... + * Subtitle2: + * item2[0] + * item2[1] + * ... + * @param title + * @param col1 + * @param col2 + */ + public static void outputTrace(String title, String subtitle1, List item1, List item1new, String subtitle2, List item2) { + if (isTracing()) { + //System.out.println(); + System.out.println(title); + final String prefix = " "; //$NON-NLS-1$ + final String doublePrefix = " "; //$NON-NLS-1$ + System.out.println(prefix + subtitle1 + " (" + item1.size() + "):"); //$NON-NLS-1$ //$NON-NLS-2$ + int count = 0; + for (Iterator i = item1.iterator(), j = item1new.iterator(); i.hasNext(); ) { + System.out.println(doublePrefix + String.valueOf(++count) + "\t\'" +(String)i.next() + (j.hasNext()?"\' -> \'" + (String)j.next():"") + '\''); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + System.out.println(prefix + subtitle2 + " (" + item2.size() + "):"); //$NON-NLS-1$ //$NON-NLS-2$ + count = 0; + for (Iterator i = item2.iterator(); i.hasNext(); ) { + System.out.println(doublePrefix + String.valueOf(++count) + "\t\'" + (String)i.next() + '\''); //$NON-NLS-1$ + } + } + } + + /** + * @param string + * @param line + */ + public static void outputError(String string, String line) { + if (isTracing()) { + System.out.println(); + System.out.println("Error: " + string + line); //$NON-NLS-1$ + } + } + + /** + * @param title + * @param subtitlePrefix + * @param subtitlePostfix + * @param map - el grande map + */ + public static void metricsTrace(String title, String subtitlePrefix, String subtitlePostfix, Map directoryCommandListMap) { + try { + logger.writeln(); + logger.writeln(" *** NEW METRICS TRACE ***"); //$NON-NLS-1$ + logger.writeln(); + for (Iterator k = directoryCommandListMap.keySet().iterator(); k.hasNext(); ) { + String dir = (String) k.next(); + logger.writeln(title + dir + ":"); //$NON-NLS-1$ + List directoryCommandList = (List) directoryCommandListMap.get(dir); + if (directoryCommandList == null) { + logger.writeln(" --- empty ---" + EOL); //$NON-NLS-1$ + return; + } + for (Iterator i = directoryCommandList.iterator(); i.hasNext(); ) { + Map command21FileListMap = (Map) i.next(); + String[] commands = (String[]) command21FileListMap.keySet().toArray(new String[1]); + logger.writeln(" " + subtitlePrefix + commands[0] + subtitlePostfix); //$NON-NLS-1$ + List fileList = (List) command21FileListMap.get(commands[0]); + for (Iterator j = fileList.iterator(); j.hasNext(); ) { + String fileName = (String) j.next(); + logger.writeln(" " + fileName); //$NON-NLS-1$ + } + } + } + logger.flushLog(); + } + catch (IOException e) {} + } + + /** + * @param title + * @param workingDirsN + * @param commandsN + * @param filesN + */ + public static void summaryTrace(String title, int workingDirsN, int commandsN, int filesN) { + try { + logger.writeln(); + logger.writeln(" *** METRICS SUMMARY ***"); //$NON-NLS-1$ + logger.writeln(); + logger.writeln(title); + logger.writeln(" Number of directories visited: " + Integer.toString(workingDirsN)); //$NON-NLS-1$ + logger.writeln(" Number of generic commands: " + Integer.toString(commandsN)); //$NON-NLS-1$ + logger.writeln(" Number of compiled files: " + Integer.toString(filesN)); //$NON-NLS-1$ + logger.flushLog(); + } + catch (IOException e) {} + } + + /** + * @param trace : String + */ + public static void metricsTrace(String trace) { + try { + logger.writeln(); + logger.writeln(" *** NEW METRICS TRACE 2 ***"); //$NON-NLS-1$ + logger.writeln(); + logger.writeln(trace); + logger.flushLog(); + } + catch (IOException e) {} + } + +} |