Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Reresubmitted: CDT2.0 Scanner Configuration discovery - initial work

Valid comments.
Resubmitting with corrections. My comments are below.

Thanks,
Vladimir Hirsl
Rational Software - IBM Software Group
Ottawa, Ontario, Canada



> Sorry, but firstly I would like to see us stick to eclipse convention
> with package naming and move the non-public classes to a internal 
package.

Done.

> Secondly there is still the question of gcc/g++ specifics being placed
> in this plugin and its not clear to me how this is extensible for other
> compilers, (It looks like there might be some interface to do this put
> its not clear when presented as just a patch). 

My intention is to separate all GNU specific stuff into extensions. I have 
already done some work in this direction. For parsing make build and 
'specs' build output I extended ErrorParser extension point. New extension 
point is defined to encapsulate generation of compiler's internal scanner 
info - SpecsBuilder. Extension to this extension point was used for GNU 
implementation (parses the output of 'generate specs' command). There are 
still some 'GNUizms' left in but I am working on separating them into 
generic and .gnu packages.

Design spec for this feature is now available on CDT web site (under PR 
47465) 
http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/cdt-home/plans/CDT_R2.0_plan.html?cvsroot=Tools_Project#Plan_Items
I hope it can answer some of your question.

I agree with the idea in Doug's and your follow up emails that all 
compiler (for now GNU) specific stuff should be moved to a separate 
plugin(s). But until the plugin is created, I guess the GNU specifics can 
reside in packages with .gnu in their name.

>Thirdly I have noticed some strange naming in the schema and in some
> javadoc..."org.vmir.cdt....." 

Done. The work started as a separate plugin :).

> 
> Please revise.
> 
> Thanks
> Dave.
> 
Index: plugin.properties
===================================================================
retrieving revision 1.2
diff -u -r1.2 plugin.properties
--- plugin.properties	19 Aug 2003 20:17:28 -0000	1.2
+++ plugin.properties	19 Feb 2004 16:17:50 -0000
@@ -3,4 +3,13 @@
 
 extensionTargetBuilder.name=Target Builder Extension
 natureMake.name=CDT Make Nature
-builderMake.name=CDT Makefile Builder
\ No newline at end of file
+builderMake.name=CDT Makefile Builder
+
+natureScannerConfig.name=Scanner Configuration Nature
+builderScannerConfig.name=Scanner Configuration Builder
+extensionSpecsBuilder.name=C/C++ Compiler Specs Builder Extension
+specsBuilder.name=Specs Builder
+
+epGnuCommandLine.name=CDT GNU C/C++ Scanner Info Parser
+epGnuCompilerSpecs.name=CDT GNU C/C++ Specs Parser
+spGnuSpecsBuilder.name=CDT GNU C/C++ Specs Builder
Index: plugin.xml
===================================================================
retrieving revision 1.11
diff -u -r1.11 plugin.xml
--- plugin.xml	5 Jan 2004 20:26:09 -0000	1.11
+++ plugin.xml	19 Feb 2004 16:17:50 -0000
@@ -21,6 +21,7 @@
 
 
    <extension-point id="MakeTargetBuilder" name="%extensionTargetBuilder.name" schema="schema/MakeTargetBuilder.exsd"/>
+   <extension-point id="SpecsBuilder" name="%extensionSpecsBuilder.name" schema="schema/SpecsBuilder.exsd"/>
 
    <extension
          id="MakeScannerProvider"
@@ -76,6 +77,74 @@
             builderID="org.eclipse.cdt.make.core.makeBuilder"
             id="org.eclipse.cdt.make.MakeTargetBuilder">
       </builder>
+   </extension>
+   <extension
+         id="GCCCommandLineParser"
+         name="%epGnuCommandLine.name"
+         point="org.eclipse.cdt.core.ErrorParser">
+      <errorparser
+            class="org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCScannerInfoParser">
+      </errorparser>
+   </extension>
+   <extension
+         id="GCCSpecsParser"
+         name="%epGnuCompilerSpecs.name"
+         point="org.eclipse.cdt.core.ErrorParser">
+      <errorparser
+            class="org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCCompilerSpecsParser">
+      </errorparser>
+   </extension>
+   <extension
+         id="ScannerConfigNature"
+         name="%natureScannerConfig.name"
+         point="org.eclipse.core.resources.natures">
+      <requires-nature
+            id="org.eclipse.cdt.make.core.makeNature">
+      </requires-nature>
+      <runtime>
+         <run
+               class="org.eclipse.cdt.make.core.scannerconfig.ScannerConfigNature">
+         </run>
+      </runtime>
+      <builder
+            id="org.eclipse.cdt.make.core.ScannerConfigBuilder">
+      </builder>
+   </extension>
+   <extension
+         id="ScannerConfigBuilder"
+         name="%builderScannerConfig.name"
+         point="org.eclipse.core.resources.builders">
+      <builder
+            hasNature="true">
+         <run
+               class="org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder">
+         </run>
+      </builder>
+   </extension>
+   <extension
+         point="org.eclipse.cdt.make.core.MakeTargetBuilder">
+      <builder
+            builderID="org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder"
+            id="org.eclipse.cdt.make.core.scannerconfig.ScannerConfigTargetBuilder">
+      </builder>
+   </extension>
+   <extension
+         id="GCCSpecsBuilder"
+         name="%spGnuSpecsBuilder.name"
+         point="org.eclipse.cdt.make.core.SpecsBuilder">
+      <specsbuilder>
+         <run
+               class="org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCSpecsBuilder">
+            <parameter
+                  name="defaultCommand"
+                  value="gcc">
+            </parameter>
+            <parameter
+                  name="defaultAttributes"
+                  value="-c -v">
+            </parameter>
+         </run>
+      </specsbuilder>
    </extension>
 
 </plugin>
Index: src/org/eclipse/cdt/make/core/MakeCorePlugin.java
===================================================================
retrieving revision 1.12
diff -u -r1.12 MakeCorePlugin.java
--- src/org/eclipse/cdt/make/core/MakeCorePlugin.java	19 Feb 2004 13:38:36 -0000	1.12
+++ src/org/eclipse/cdt/make/core/MakeCorePlugin.java	19 Feb 2004 16:17:50 -0000
@@ -1,5 +1,5 @@
 /**********************************************************************
- * Copyright (c) 2002,2003 QNX Software Systems and others.
+ * Copyright (c) 2002,2004 QNX Software Systems and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
 ***********************************************************************/
 package org.eclipse.cdt.make.core;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
@@ -19,13 +21,21 @@
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.make.core.makefile.IMakefile;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder;
 import org.eclipse.cdt.make.internal.core.BuildInfoFactory;
 import org.eclipse.cdt.make.internal.core.MakeTargetManager;
 import org.eclipse.cdt.make.internal.core.makefile.gnu.GNUMakefile;
+import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerConfigInfoFactory;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IPluginDescriptor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
@@ -40,6 +50,13 @@
 	public static final String MAKE_PROJECT_ID = MakeCorePlugin.getUniqueIdentifier() + ".make"; //$NON-NLS-1$
 	private MakeTargetManager fTargetManager;
 	public static final String OLD_BUILDER_ID = "org.eclipse.cdt.core.cbuilder"; //$NON-NLS-1$
+
+	public static final String SPECS_BUILDER_SIMPLE_ID = "SpecsBuilder"; //$NON-NLS-1$
+	public static final String GCC_SPECS_BUILDER_ID = MakeCorePlugin.getUniqueIdentifier() + ".GCCSpecsBuilder"; //$NON-NLS-1$
+	
+	public static final String CPP_SPECS_FILE = "specs.cpp"; //$NON-NLS-1$ 
+	public static final String C_SPECS_FILE = "specs.c";  //$NON-NLS-1$
+
 	//The shared instance.
 	private static MakeCorePlugin plugin;
 	//Resource bundle.
@@ -56,6 +73,7 @@
 		} catch (MissingResourceException x) {
 			resourceBundle = null;
 		}
+		createSpecs();
 	}
 
 	/**
@@ -131,6 +149,16 @@
 		} catch (CoreException e) {
 		}
 		getPluginPreferences().setDefault(CCorePlugin.PREF_BINARY_PARSER, CCorePlugin.PLUGIN_ID + ".ELF"); //$NON-NLS-1$
+
+		// default plugin preferences for scanner configuration discovery
+		IScannerConfigBuilderInfo scInfo = createScannerConfigBuildInfo(getPluginPreferences(), ScannerConfigBuilder.BUILDER_ID, true);
+		try {
+			scInfo.setAutoDiscoveryEnabled(false);
+			scInfo.setUseDefaultSpecsCmd(true);
+			scInfo.setSpecsCommand(new Path("gcc")); //$NON-NLS-1$
+			scInfo.setSpecsArguments("-c -v");	//$NON-NLS-1$
+		} catch (CoreException e) {
+		}
 	}
 	
 	public static IMakeBuilderInfo createBuildInfo(Preferences prefs, String builderID, boolean useDefaults) {
@@ -177,6 +205,85 @@
 			fTargetManager.shutdown();
 			fTargetManager = null;
 		}
+	}
+
+	/*
+	 * Following methods create IScannerConfigBuilderInfo
+	 * Delegating requests to ScannerConfigInfoFactory
+	 */
+	public static IScannerConfigBuilderInfo createScannerConfigBuildInfo(
+			Preferences prefs, String builderID, boolean useDefaults) {
+		return ScannerConfigInfoFactory.create(prefs, builderID, useDefaults);
+	}
+
+	public static IScannerConfigBuilderInfo createScannerConfigBuildInfo(
+			IProject project, String builderID) throws CoreException {
+		return ScannerConfigInfoFactory.create(project, builderID);
+	}
+
+	public static IScannerConfigBuilderInfo createScannerConfigBuildInfo(
+			Map args, String builderID) {
+		return ScannerConfigInfoFactory.create(args, builderID);
+	}
+	
+	public static IPath getWorkingDirectory() {
+		return MakeCorePlugin.getDefault().getStateLocation();
+	}
+
+	private void createSpecs() {
+		IPath path = getWorkingDirectory();
+		try {
+			createSpecsFile(path, CPP_SPECS_FILE);
+			createSpecsFile(path, C_SPECS_FILE);
+		} catch (CoreException e) {
+			log(e);
+		}
+	}
+
+	private 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.getDefault().getDescriptor().getUniqueIdentifier(),
+						-1, "Error writing specs file", e));
+			}
+		}
+	}
+
+	/**
+	 * @param toolset - id specifying compiler toolset i.e. GCC
+	 * @return builder - new instance of a 'specs' builder
+	 */
+	public ISpecsBuilder loadSpecsBuilder(String id) {
+		ISpecsBuilder[] empty = new ISpecsBuilder[0];
+		try {
+			IExtensionPoint extension = getDescriptor().getExtensionPoint(SPECS_BUILDER_SIMPLE_ID);
+			if (extension != null) {
+				IExtension[] extensions = extension.getExtensions();
+				for (int i = 0; i < extensions.length; i++) {
+					String tool = extensions[i].getUniqueIdentifier();
+					if (tool != null && tool.equals(id)) {
+						IConfigurationElement[] configElements = extensions[i]. getConfigurationElements();
+						for (int j = 0; j < configElements.length; j++) {
+							IConfigurationElement[] runElement = configElements[j].getChildren("run"); //$NON-NLS-1$
+							if (runElement.length > 0) { 
+								ISpecsBuilder builder = (ISpecsBuilder) runElement[0].createExecutableExtension("class");
+								return builder;
+							}
+						}
+					}
+				}
+			}
+		} catch (CoreException e) {
+			log(e);
+		}
+		return null;
 	}
 
 }
Index: src/org/eclipse/cdt/make/core/PluginResources.properties
===================================================================
retrieving revision 1.5
diff -u -r1.5 PluginResources.properties
--- src/org/eclipse/cdt/make/core/PluginResources.properties	19 Feb 2004 13:38:36 -0000	1.5
+++ src/org/eclipse/cdt/make/core/PluginResources.properties	19 Feb 2004 16:17:51 -0000
@@ -7,8 +7,28 @@
 
 BuildInfoFactory.Missing_Builder=Missing Builder: 
 
+<<<<<<< PluginResources.properties
+MakeTargetProvider.add_to_workspace_root=Cannot add build targets to workspace root
+MakeTargetProvider.add_temporary_target=Cannot add temporart Target to manager.
+MakeTargetProvider.target_exists=Target exists
+MakeTargetProvider.failed_initializing_targets=Failed initializing build targets
+
+ScannerConfigBuilder.Invoking_Builder=Scanner Configuration update ... 
+
+SpecsBuilder.Build_Error=Error launching builder ({0})
+SpecsBuilder.Reading_Specs=Reading specs ... 
+SpecsBuilder.Parsing_Output=Parsing output... 
+SpecsBuidler.Creating_Markers=Generating markers...
+
+ScannerInfoCollector.Processing=Processing discovered scanner configuration ... 
+ScannerInfoCollector.Updating=Updating Scanner Configuration for project 
+
+=======
 MakeTargetManager.add_to_workspace_root=Cannot add build targets to workspace root
 MakeTargetManager.add_temporary_target=Cannot add temporart Target to manager.
 MakeTargetManager.target_exists=Target exists
 MakeTargetManager.failed_initializing_targets=Failed initializing build targets
 MakeTargetManager.error_writing_file=Error writing target file
+>>>>>>> 1.5
Index: schema/SpecsBuilder.exsd
===================================================================
RCS file: schema/SpecsBuilder.exsd
diff -N schema/SpecsBuilder.exsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ schema/SpecsBuilder.exsd	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,137 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.cdt.make.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.cdt.make.core" id="SpecsBuilders" name="C/C++ Compiler Specs Builder"/>
+      </appInfo>
+      <documentation>
+         This extension point is used to plug in particular compiler specs builder.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="specsbuilder" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="specsbuilder">
+      <complexType>
+         <sequence>
+            <element ref="run"/>
+         </sequence>
+      </complexType>
+   </element>
+
+   <element name="run">
+      <complexType>
+         <sequence>
+            <element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A fully qualified name of the Java class that implements &lt;samp&gt;org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder&lt;/samp&gt; interface.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="parameter">
+      <annotation>
+         <documentation>
+            Parameters passed to the specs builder.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="name" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Name of a parameter.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="value" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Value of a parameter.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         Plug-ins that want to extend this extension point must implement &lt;samp&gt;org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder&lt;/samp&gt; interface.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         org.eclipse.cdt.make.core plugin provides default implementation of the GNU C/C++ compiler specs builder.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
Index: src/org/eclipse/cdt/make/core/scannerconfig/IScannerConfigBuilderInfo.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/IScannerConfigBuilderInfo.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/IScannerConfigBuilderInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/IScannerConfigBuilderInfo.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,34 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.cdt.make.core.scannerconfig;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Settings for ScannerConfigBuilder
+ * 
+ * @author vhirsl
+ */
+public interface IScannerConfigBuilderInfo {
+	boolean isAutoDiscoveryEnabled();
+	void setAutoDiscoveryEnabled(boolean enabled) throws CoreException;
+
+	boolean isDefaultSpecsCmd();
+	void setUseDefaultSpecsCmd(boolean on) throws CoreException;
+
+	IPath getSpecsCommand();
+	void setSpecsCommand(IPath command) throws CoreException;
+
+	String getSpecsArguments();
+	void setSpecsArguments(String args) throws CoreException;
+}
Index: src/org/eclipse/cdt/make/core/scannerconfig/ISpecsBuilder.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/ISpecsBuilder.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/ISpecsBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/ISpecsBuilder.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,40 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.core.scannerconfig;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Interface for C/++ specs builders
+ * 
+ * @author vhirsl
+ */
+public interface ISpecsBuilder {
+	/**
+	 * Initializes specs builder
+	 * 
+	 * @param workingDirectory - where the compiler will be invoked
+	 * @param current project - current project being built
+	 * @return boolean - successful initialization
+	 */
+	public boolean initialize(IPath workingDirectory, IScannerConfigBuilderInfo buildInfo, IProject currentProject);
+	/**
+	 * Invokes a C/C++ compiler with target specific options to generate
+	 * compiler specs.
+	 * 
+	 * @param monitor
+	 * @param buildInfo - settings for ScannerConfigBuilder
+	 * @param targetSpecificOptions - array of options affecting compiler specs
+	 */
+	public boolean invokeCompiler(IProgressMonitor monitor, String[] targetSpecificOptions);
+}
Index: src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigBuilder.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigBuilder.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigBuilder.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,45 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.core.scannerconfig;
+
+import org.eclipse.cdt.core.resources.ACBuilder;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.internal.core.scannerconfig.*;
+import org.eclipse.core.resources.IProject;
+import java.util.Map;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.SubProgressMonitor;
+
+/**
+ * Runs after standard make builder.
+ * Consolidates discovered scanner configuration and updates project's scanner configuration.
+ * 
+ * @see IncrementalProjectBuilder
+ */
+public class ScannerConfigBuilder extends ACBuilder {
+	public final static String BUILDER_ID = MakeCorePlugin.getUniqueIdentifier() + ".ScannerConfigBuilder"; //$NON-NLS-1$
+
+	public ScannerConfigBuilder() {
+		super();
+	}
+
+	/**
+	 * @see IncrementalProjectBuilder#build
+	 */
+	protected IProject [] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
+		monitor.beginTask("", 100); //$NON-NLS-1$
+		// TODO: correct the monitor's text
+		monitor.subTask(MakeCorePlugin.getResourceString("ScannerConfigBuilder.Invoking_Builder") + getProject().getName());
+		ScannerInfoCollector.getInstance().updateScannerConfiguration(getProject(), new SubProgressMonitor(monitor, 100));
+		return getProject().getReferencedProjects();
+	}
+}
Index: src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigNature.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigNature.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigNature.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/ScannerConfigNature.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,131 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.core.scannerconfig;
+
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+
+/**
+ * @see IProjectNature
+ */
+public class ScannerConfigNature implements IProjectNature {
+	
+	public final static String NATURE_ID = MakeCorePlugin.getUniqueIdentifier() + ".ScannerConfigNature"; //$NON-NLS-1$
+	private IProject fProject;
+
+	/**
+	 *
+	 */
+	public ScannerConfigNature() {
+	}
+
+	/**
+	 * @see IProjectNature#configure
+	 */
+	public void configure() throws CoreException {
+		IProjectDescription description = getProject().getDescription();
+		ICommand[] commands = description.getBuildSpec();
+		for (int i = 0; i < commands.length; ++i) {
+			if (commands[i].getBuilderName().equals(ScannerConfigBuilder.BUILDER_ID)) {
+				return;
+			}
+		}
+		ICommand command = description.newCommand();
+		command.setBuilderName(ScannerConfigBuilder.BUILDER_ID);
+		ICommand[] newCommands = new ICommand[commands.length + 1];
+		System.arraycopy(commands, 0, newCommands, 0, commands.length);
+		newCommands[commands.length] = command;
+		description.setBuildSpec(newCommands);
+		getProject().setDescription(description, null);
+	}
+
+	/**
+	 * @see IProjectNature#deconfigure
+	 */
+	public void deconfigure() throws CoreException {
+		IProjectDescription description = getProject().getDescription();
+		ICommand[] commands = description.getBuildSpec();
+		for (int i = 0; i < commands.length; ++i) {
+			if (commands[i].getBuilderName().equals(ScannerConfigBuilder.BUILDER_ID)) {
+				ICommand[] newCommands = new ICommand[commands.length - 1];
+				System.arraycopy(commands, 0, newCommands, 0, i);
+				System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
+				description.setBuildSpec(newCommands);
+				break;
+			}
+		}
+		getProject().setDescription(description, null);
+	}
+
+	/**
+	 * @see IProjectNature#getProject
+	 */
+	public IProject getProject()  {
+		return fProject;
+	}
+
+	/**
+	 * @see IProjectNature#setProject
+	 */
+	public void setProject(IProject project)  {
+		fProject = project;
+	}
+	
+	static public void addScannerConfigNature(IProject project) throws CoreException {
+		if (project.hasNature(NATURE_ID))
+			return;
+		
+		IProjectDescription description = project.getDescription();
+		String[] ids = description.getNatureIds();
+		String[] newIds = new String[ids.length + 1];
+		System.arraycopy(ids, 0, newIds, 0, ids.length);
+		newIds[ids.length] = NATURE_ID;
+		description.setNatureIds(newIds);
+		project.setDescription(description, null);
+	}
+	
+	static public void removeScannerConfigNature(IProject project) throws CoreException {
+		IProjectDescription description = project.getDescription();
+		String[] ids = description.getNatureIds();
+		for (int i = 0; i < ids.length; ++i) {
+			if (ids[i].equals(NATURE_ID)) {
+				String[] newIds = new String[ids.length - 1];
+				System.arraycopy(ids, 0, newIds, 0, i);
+				System.arraycopy(ids, i + 1, newIds, i, ids.length - i - 1);
+				description.setNatureIds(newIds);
+				project.setDescription(description, null);
+			}
+		}
+	}
+
+	/**
+	 * Returns build command as stored in .project file
+	 * 
+	 * @param project
+	 * @param builderID
+	 * @return ICommand
+	 * @throws CoreException
+	 */
+	public static ICommand getBuildSpec(IProject project, String builderID) throws CoreException {
+		IProjectDescription description = project.getDescription();
+		ICommand[] commands = description.getBuildSpec();
+		for (int i = 0; i < commands.length; ++i) {
+			if (commands[i].getBuilderName().equals(builderID)) {
+				return commands[i];
+			}
+		}
+		return null;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerConfigInfoFactory.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,259 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-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.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.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigNature;
+
+/**
+ * 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 USE_DEFAULT_SPECS_CMD = PREFIX + ".useDefaultSpecsCmd"; //$NON-NLS-1$
+	static final String SPECS_COMMAND = PREFIX + ".specsCommand"; //$NON-NLS-1$
+	static final String SPECS_ARGUMENTS = PREFIX + ".specsArguments"; //$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#isDefaultSpecsCmd()
+		 */
+		public boolean isDefaultSpecsCmd() {
+			if (getString(USE_DEFAULT_SPECS_CMD) == null ||
+				getString(USE_DEFAULT_SPECS_CMD).length() == 0) { // if no property then default to true
+				return true;
+			}
+			return getBoolean(USE_DEFAULT_SPECS_CMD);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setUseDefaultSpecsCmd(boolean)
+		 */
+		public void setUseDefaultSpecsCmd(boolean on) throws CoreException {
+			putString(USE_DEFAULT_SPECS_CMD, Boolean.toString(on));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getSpecsCommand()
+		 */
+		public IPath getSpecsCommand() {
+			if (isDefaultSpecsCmd()) {
+				String command = getSpecsParameter("defaultCommand"); //$NON-NLS-1$
+				if (command == null) {
+					return new Path("gcc"); //$NON-NLS-1$
+				}
+				return new Path(command);
+			}
+			return new Path(getString(SPECS_COMMAND));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setSpecsCommand(org.eclipse.core.runtime.IPath)
+		 */
+		public void setSpecsCommand(IPath command) throws CoreException {
+			putString(SPECS_COMMAND, command.toString());
+		}
+		
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getSpecsArguments()
+		 */
+		public String getSpecsArguments() {
+			if (isDefaultSpecsCmd()) {
+				String command = getSpecsParameter("defaultAttributes"); //$NON-NLS-1$
+				if (command == null) {
+					command = "-c -v"; //$NON-NLS-1$
+				}
+				return command;
+			}
+			return getString(SPECS_ARGUMENTS);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setSpecsArguments(java.lang.String)
+		 */
+		public void setSpecsArguments(String args) throws CoreException {
+			putString(SPECS_ARGUMENTS, args);
+		}
+
+		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 getSpecsParameter(String name) {
+			IExtension extension =
+				Platform.getPluginRegistry().getExtension(
+						MakeCorePlugin.getUniqueIdentifier(),
+						MakeCorePlugin.SPECS_BUILDER_SIMPLE_ID,
+// TODO VMIR account for possible multiple available specs builders
+						MakeCorePlugin.GCC_SPECS_BUILDER_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;
+		}
+	}
+	
+	/**
+	 *
+	 * @author vhirsl
+	 */
+	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, builderID);
+			if (builder == null) {
+				throw new CoreException(new Status(IStatus.ERROR,
+						MakeCorePlugin.getUniqueIdentifier(), -1,
+						MakeCorePlugin.getResourceString("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;
+			}
+			ICommand builder = ScannerConfigNature.getBuildSpec(project, builderID);
+			args.put(name, value);
+			builder.setArguments(args);
+			project.setDescription(project.getDescription(), 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);
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoCollector.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoCollector.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoCollector.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoCollector.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,330 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCProjectNature;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.core.resources.IProject;
+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.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.cdt.make.core.MakeScannerInfo;
+import org.eclipse.cdt.make.core.MakeProjectNature;
+
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder;
+import org.eclipse.cdt.make.internal.core.scannerconfig.util.CygpathTranslator;
+import org.eclipse.cdt.make.internal.core.scannerconfig.util.ScannerConfigUtil;
+
+
+/**
+ * Singleton object that collects scanner config updates from ScannerInfoParser
+ * and updates scanner config when the project's build is done.
+ *
+ * @author vhirsl
+ */
+public class ScannerInfoCollector { 
+
+	// Singleton
+	private static ScannerInfoCollector instance = new ScannerInfoCollector();
+	private Map discoveredIncludes; 
+	private Map discoveredSymbols;
+	private Map discoveredTSO;	// target specific options
+	// cumulative values
+	private Map sumDiscoveredIncludes; 
+	private Map sumDiscoveredSymbols;
+	private Map sumDiscoveredTSO;	// target specific options
+	
+	private IProject currentProject;	// project being built
+	
+	private ScannerInfoCollector() {
+		discoveredIncludes = new HashMap();
+		discoveredSymbols = new HashMap();
+		discoveredTSO = new HashMap();
+		
+		sumDiscoveredIncludes = new HashMap();
+		sumDiscoveredSymbols = new HashMap();
+		sumDiscoveredTSO = new HashMap();
+	}
+	
+	public static ScannerInfoCollector getInstance() {
+		return instance;
+	}
+
+	/**
+	 * Published method to receive per file contributions to ScannerInfo
+	 * 
+	 * @param project
+	 * @param includes
+	 * @param symbols
+	 * @param targetSpecificOptions
+	 */
+	public synchronized void contributeToScannerConfig(IProject project, List includes, List symbols, List targetSpecificOptions) {
+		try {
+			if (project.hasNature(MakeProjectNature.NATURE_ID) && // limits to StandardMake projects
+					(project.hasNature(CProjectNature.C_NATURE_ID) ||
+					 project.hasNature(CCProjectNature.CC_NATURE_ID))) { 
+
+				String projectName = project.getName();
+				contribute(projectName, discoveredIncludes, includes);
+				contribute(projectName, discoveredSymbols, symbols);
+				contribute(projectName, discoveredTSO, targetSpecificOptions);
+			}
+		} 
+		catch (CoreException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * Published method to receive compiler specified contributions to ScannerInfo
+	 * 
+	 * @param includes
+	 * @param symbols
+	 */
+	public void contributeToScannerConfig(List includes, List symbols) {
+		contributeToScannerConfig(currentProject, includes, symbols, null);
+	}
+
+	/**
+	 * @param project
+	 * @param discovered symbols | includes | targetSpecificOptions
+	 * @param delta symbols | includes | targetSpecificOptions
+	 * @return true if there is a change in discovered symbols | includes | targetSpecificOptions
+	 */
+	private boolean contribute(String projectName, Map discovered, List delta) {
+		if (delta == null || delta.isEmpty())
+			return false;
+		List projectDiscovered = (List) discovered.get(projectName);
+		if (projectDiscovered == null) {
+			projectDiscovered = new ArrayList(delta);
+			discovered.put(projectName, projectDiscovered);
+			return true;
+		}
+		boolean added = false;
+		for (Iterator i = delta.iterator(); i.hasNext(); ) {
+			String item = (String) i.next();
+			if (!projectDiscovered.contains(item)) {
+				added |= projectDiscovered.add(item);
+			}
+		}
+		return added;
+	}
+
+	/**
+	 * @param project
+	 * @param monitor
+	 */
+	private void updateScannerConfig(IProject project, IProgressMonitor monitor) {
+		IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
+		monitor.beginTask(MakeCorePlugin.getResourceString("ScannerInfoCollector.Processing"), 100);
+		if (provider != null) {
+			IScannerInfo scanInfo = provider.getScannerInformation(project);
+			if (scanInfo != null) {
+				if (scanInfo instanceof MakeScannerInfo) {
+					MakeScannerInfo makeScanInfo = (MakeScannerInfo)scanInfo;
+					String projectName = project.getName();
+					
+					monitor.subTask(MakeCorePlugin.getResourceString("ScannerInfoCollector.Processing"));
+					if (scannerConfigNeedsUpdate(makeScanInfo, projectName)) {
+						monitor.worked(50);
+						monitor.subTask(MakeCorePlugin.getResourceString("ScannerInfoCollector.Updating") + projectName);
+						
+						try {
+							// update scanner configuration
+							makeScanInfo.update();
+							monitor.worked(50);
+						} catch (CoreException e) {
+							// TODO : VMIR create a marker?
+							MakeCorePlugin.log(e);
+						}
+					}
+				}
+			}
+		}
+		monitor.done();
+	}
+
+	/**
+	 * Compare discovered include paths and symbol definitions with the ones from scanInfo.
+	 * @param scanInfo
+	 * @param projectName
+	 * @return
+	 */
+	private boolean scannerConfigNeedsUpdate(MakeScannerInfo makeScanInfo, String projectName) {
+		// TODO : VMIR to implement other variants
+		List includes = (List) discoveredIncludes.get(projectName);
+		Set symbols = new HashSet((List) discoveredSymbols.get(projectName));
+		if (includes == null && symbols == null)
+			return false;
+		
+		// Step 1. Add discovered scanner config to the existing discovered scanner config 
+		// add the includes from the latest discovery
+		boolean addedIncludes = false;
+		List sumIncludes = (List) sumDiscoveredIncludes.get(projectName);
+		if (sumIncludes == null) {
+			sumIncludes = new ArrayList(includes);
+			sumDiscoveredIncludes.put(projectName, sumIncludes);
+			addedIncludes = true;
+		}
+		else {
+			for (Iterator i = includes.iterator(); i.hasNext(); ) {
+				String include = (String) i.next();
+				if (!sumIncludes.contains(include)) {
+					addedIncludes |= sumIncludes.add(include);
+				}
+			}
+		}
+		// try to translate cygpaths to absolute paths
+		List finalSumIncludes = translateIncludePaths(sumIncludes);
+		
+		// add the symbols from the latest discovery
+		boolean addedSymbols = false;
+		Map sumSymbols = (Map) sumDiscoveredSymbols.get(projectName);
+		if (sumSymbols == null) {
+			sumSymbols = new HashMap();
+			sumDiscoveredSymbols.put(projectName, sumSymbols);
+		}
+		addedSymbols = ScannerConfigUtil.scAddSymbolsSet2SymbolEntryMap(sumSymbols, symbols, false);
+		
+		// Step 2. Get project's scanner config
+		String[] persistedIncludes = makeScanInfo.getIncludePaths();
+		Map persistedSymbols = makeScanInfo.getDefinedSymbols();
+		
+		// TODO VMIR this is likely to change when new UI is introduced
+		// Step 3. Merge scanner config from steps 1 and 2
+		List candidateIncludes = new ArrayList(Arrays.asList(persistedIncludes));
+		for (Iterator i = finalSumIncludes.iterator(); i.hasNext(); ) {
+			String include = (String) i.next();
+			if (!candidateIncludes.contains(include)) {
+				addedIncludes |= candidateIncludes.add(include);
+			}
+		}
+		Map candidateSymbols = new HashMap(sumSymbols);
+		Set persistedSymbolsSet = ScannerConfigUtil.scSymbolsMap2Set(persistedSymbols);
+		addedSymbols |= ScannerConfigUtil.scAddSymbolsSet2SymbolEntryMap(candidateSymbols, persistedSymbolsSet, true);
+		
+		// Step 4. Set resulting scanner config
+		makeScanInfo.setIncludePaths((String[])candidateIncludes.toArray(new String[candidateIncludes.size()]));
+		makeScanInfo.setPreprocessorSymbols((String[])ScannerConfigUtil.
+			scSymbolsSymbolEntryMap2Set(candidateSymbols).toArray(new String[candidateSymbols.size()]));
+		
+		// invalidate discovered include paths and symbol definitions
+		discoveredIncludes.put(projectName, null);
+		discoveredSymbols.put(projectName, null);
+		
+		return (addedIncludes | addedSymbols);
+	}
+
+	/**
+	 * @param sumIncludes
+	 * @return
+	 */
+	private List translateIncludePaths(List 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()) {
+				String translatedPath = new CygpathTranslator(currentProject, includePath).run();
+				if (!translatedPath.equals(includePath)) {
+					// Check if the translated path exists
+					IPath transPath = new Path(translatedPath);
+					if (transPath.toFile().exists()) {
+						translatedIncludePaths.add(translatedPath);
+					}
+					else {
+						// TODO VMIR create problem marker
+					}
+				}
+			}
+		}
+		return translatedIncludePaths;
+	}
+
+	private void getCompilerScannerInfo(final IProject project, 
+										final List tso, 
+										final IProgressMonitor monitor) {
+		// Call specs builder to get compiler's scanner info
+		final ISpecsBuilder specsBuilder = MakeCorePlugin.getDefault().
+										   loadSpecsBuilder(MakeCorePlugin.GCC_SPECS_BUILDER_ID);
+		if (specsBuilder != null) {
+			// get IScannerConfigBuilderInfo
+			IScannerConfigBuilderInfo info;
+			try {
+				info = MakeCorePlugin.createScannerConfigBuildInfo(
+						project, ScannerConfigBuilder.BUILDER_ID);
+			}
+			catch (CoreException e) {
+				MakeCorePlugin.log(e);
+				info = MakeCorePlugin.createScannerConfigBuildInfo(
+						MakeCorePlugin.getDefault().getPluginPreferences(), 
+						ScannerConfigBuilder.BUILDER_ID, false);
+			}
+			final IScannerConfigBuilderInfo buildInfo = info;
+			
+			ISafeRunnable runnable = new ISafeRunnable() {
+				public void run() {
+					if (specsBuilder.initialize(MakeCorePlugin.getWorkingDirectory(), buildInfo, project)) {
+						if (tso == null) {
+							specsBuilder.invokeCompiler(monitor, new String[0]);
+						}
+						else {
+							specsBuilder.invokeCompiler(monitor, (String[])tso.toArray(new String[tso.size()]));
+						}
+					}
+				}
+	
+				public void handleException(Throwable exception) {
+					MakeCorePlugin.log(exception);
+				}
+			};
+			Platform.run(runnable);
+		}
+	}
+
+	/**
+	 * @param project
+	 * @param monitor
+	 */
+	public synchronized void updateScannerConfiguration(IProject project, IProgressMonitor monitor) {
+		currentProject = project;
+		String projectName = project.getName();
+		// check TSO for the project
+		monitor.beginTask("", 100); //$NON-NLS-1$
+		getCompilerScannerInfo(project, (List) discoveredTSO.get(projectName), new SubProgressMonitor(monitor, 60));
+		updateScannerConfig(project, new SubProgressMonitor(monitor, 40));
+
+		// delete discovered scanner config
+		discoveredIncludes.put(projectName, null);
+		discoveredSymbols.put(projectName, null);
+		discoveredTSO.put(projectName, null);
+	}
+
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCCompilerSpecsParser.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCCompilerSpecsParser.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCCompilerSpecsParser.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCCompilerSpecsParser.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,90 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig.gnu;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IErrorParser;
+
+import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoCollector;
+
+/**
+ * Parses output of gcc -c -v specs.c or
+ *                  g++ -c -v specs.cpp
+ * command
+ * 
+ * @author vhirsl
+ */
+public class GCCCompilerSpecsParser implements IErrorParser {
+	private final int STATE_BEGIN = 0;
+	private final int STATE_SPECS_STARTED = 1;
+	private final int STATE_INCLUDES_STARTED = 2;
+	
+	private int state = STATE_BEGIN;
+	private List symbols = new ArrayList();
+	private List includes = new ArrayList();
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.IErrorParser#processLine(java.lang.String, org.eclipse.cdt.core.ErrorParserManager)
+	 */
+	public boolean processLine(String line, ErrorParserManager eoParser) {
+		boolean rc = false;
+		// Known patterns:
+		// (a) gcc|g++ ... -Dxxx -Iyyy ...
+		switch (state) {
+			case STATE_BEGIN:
+				if (line.startsWith("Reading specs from")) {	//$NON-NLS-1$
+					state = STATE_SPECS_STARTED;
+				}
+				return rc;
+			case STATE_SPECS_STARTED: 
+				if (line.indexOf("-D") != -1) {	//$NON-NLS-1$
+					// line contains -Ds, extract them
+					StringTokenizer scanner = new StringTokenizer(line);
+					if (scanner.countTokens() <= 1)
+						return rc;
+					for (String token = scanner.nextToken(); scanner.hasMoreTokens(); token = scanner.nextToken()) {
+						if (token.startsWith("-D")) {	//$NON-NLS-1$
+							String symbol = token.substring(2);
+							if (!symbols.contains(symbol))
+								symbols.add(symbol);
+						}
+					}
+				}
+				// now get all the includes
+				if (line.startsWith("#include") && line.endsWith("search starts here:")) { //$NON-NLS-1$ //$NON-NLS-2$
+					state = STATE_INCLUDES_STARTED;
+				}
+				return rc;
+			case STATE_INCLUDES_STARTED:
+				if (line.startsWith("#include") && line.endsWith("search starts here:")) { //$NON-NLS-1$ //$NON-NLS-2$
+					state = STATE_INCLUDES_STARTED;
+				}
+				else if (line.startsWith("End of search list.")) {	//$NON-NLS-1$
+					state = STATE_BEGIN;
+					break;
+				}
+				else {
+					if (!includes.contains(line))
+						includes.add(line);
+				}
+				return rc;
+			}
+			
+		ScannerInfoCollector.getInstance().contributeToScannerConfig(includes, symbols);
+			
+		return rc;
+	}
+
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoParser.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoParser.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoParser.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoParser.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,123 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig.gnu;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IErrorParser;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoCollector;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Parses gcc and g++ output for -I and -D parameters.
+ * 
+ * @author vhirsl
+ */
+public class GCCScannerInfoParser implements IErrorParser {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.IErrorParser#processLine(java.lang.String, org.eclipse.cdt.core.ErrorParserManager)
+	 */
+	public boolean processLine(String line, ErrorParserManager eoParser) {
+		boolean rc = false;
+		// Known patterns:
+		// (a) gcc|g++ ... -Dxxx -Iyyy ...
+		StringTokenizer scanner = new StringTokenizer(line);
+		if (scanner.countTokens() <= 1)
+			return false;
+		String token = scanner.nextToken();
+		if (token.equalsIgnoreCase("gcc") || token.equalsIgnoreCase("g++")) {//$NON-NLS-1$ //$NON-NLS-2$
+			// Recognized gcc or g++ compiler invocation
+			List includes = new ArrayList();
+			List symbols = new ArrayList();
+			List targetSpecificOptions = new ArrayList();
+
+			rc = true;
+			String fileName = null;
+			String desc = "Found";
+			while (scanner.hasMoreTokens()) {
+				token = scanner.nextToken();
+				if (token.startsWith("-D")) {//$NON-NLS-1$
+					String symbol = token.substring(2);
+					if (!symbols.contains(symbol))
+						symbols.add(symbol);
+				}
+				else if (token.startsWith("-I")) {//$NON-NLS-1$
+					String iPath = token.substring(2);
+					if (!includes.contains(iPath))
+						includes.add(iPath);
+				}
+				else if (token.equals("-mwin32") ||		//$NON-NLS-1$
+						 token.equals("-mno-win32") ||	//$NON-NLS-1$
+						 token.equals("-mno-cygwin") ||	//$NON-NLS-1$
+						 token.equals("-ansi") ||		//$NON-NLS-1$
+						 token.equals("-nostdinc")) {	//$NON-NLS-1$
+					if (!targetSpecificOptions.contains(token))
+						targetSpecificOptions.add(token);
+				}
+				else {
+					String possibleFileName = token.toLowerCase();
+					if (possibleFileName.endsWith(".c") || 			//$NON-NLS-1$
+							possibleFileName.endsWith(".cpp") ||	//$NON-NLS-1$
+							possibleFileName.endsWith(".cc") ||		//$NON-NLS-1$
+							possibleFileName.endsWith(".cxx")) {	//$NON-NLS-1$
+						fileName = token;
+					}
+				}
+			}
+			
+			IFile file = null;
+			if (fileName != null) {
+				file = eoParser.findFilePath(fileName);
+	
+				if (file == null) {
+					// Parse the entire project.
+					file = eoParser.findFileName(fileName);
+					if (file != null) {
+						// If there is a conflict set the error on the project.
+						if (eoParser.isConflictingName(fileName)) {
+							desc = "*" + desc;
+							file = null;
+						}
+					}
+				}
+				
+				// Contribute discovered includes and symbols to the ScannerInfoCollector
+				if (file != null) {
+					IProject project = file.getProject();
+					ScannerInfoCollector.getInstance().
+						contributeToScannerConfig(project, includes, symbols, targetSpecificOptions);
+				}
+			}
+			
+			// TODO : VMIR remove when debugging is done
+			int severity = IMarkerGenerator.SEVERITY_INFO;
+			
+			for (Iterator i = includes.iterator(); i.hasNext(); ) {
+				String iPath = (String)i.next();
+				eoParser.generateMarker(file, -1, "Found an include path: "+iPath, severity, iPath);
+			}
+			for (Iterator i = symbols.iterator(); i.hasNext(); ) {
+				String symbol = (String)i.next();
+				eoParser.generateMarker(file, -1, "Found a symbol definition: "+symbol, severity, symbol);
+			}
+			
+		}
+		return false;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsBuilder.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsBuilder.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsBuilder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsBuilder.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,271 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig.gnu;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.eclipse.cdt.core.CCProjectNature;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.core.model.ICModelMarker;
+import org.eclipse.cdt.core.resources.IConsole;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder;
+import org.eclipse.cdt.make.internal.core.StreamMonitor;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+
+/**
+ * New type
+ * 
+ * @author vhirsl
+ */
+public class GCCSpecsBuilder implements ISpecsBuilder, IMarkerGenerator {
+	
+	private static final String BUILD_ERROR = "SpecsBuilder.Build_Error"; //$NON-NLS-1$
+	private static final String SPECS_ERROR_PARSER = MakeCorePlugin.getUniqueIdentifier() + ".GCCSpecsParser"; //$NON-NLS-1$
+	private static final String SPECS_BUILDER_CONSOLE_ID = MakeCorePlugin.getUniqueIdentifier() + ".SpecsBuilderConsole";	//$NON-NLS-1$
+	
+	private IPath workingDirectory;
+	private IProject currentProject;
+	private IPath fCompileCommand;
+	private String fCompileArguments = null;
+	private String targetFile;
+	private IScannerConfigBuilderInfo fBuildInfo;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder#initialize(org.eclipse.core.runtime.IPath, org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo, org.eclipse.core.resources.IProject)
+	 */
+	public boolean initialize(IPath workingDirectory, IScannerConfigBuilderInfo buildInfo, IProject currentProject) {
+		boolean rc = false;
+		this.workingDirectory = workingDirectory;
+		this.currentProject = currentProject;
+		this.fBuildInfo = buildInfo;
+		try {
+			fCompileCommand = fBuildInfo.getSpecsCommand();
+			if (fCompileCommand != null) {
+				fCompileArguments = fBuildInfo.getSpecsArguments();
+				if (currentProject.hasNature(CCProjectNature.CC_NATURE_ID)) {
+					targetFile = MakeCorePlugin.CPP_SPECS_FILE;
+				}
+				else if (currentProject.hasNature(CProjectNature.C_NATURE_ID)) {
+					targetFile = MakeCorePlugin.C_SPECS_FILE;
+				}
+				rc = true;
+			}
+		} catch (CoreException e) {
+			fCompileCommand = null;
+			CCorePlugin.log(e);
+		}
+		return rc;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.ISpecsBuilder#invokeCompiler(org.eclipse.core.runtime.IProgressMonitor, java.lang.String[])
+	 */
+	public boolean invokeCompiler(IProgressMonitor monitor, String[] targetSpecificOptions) {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		monitor.beginTask(MakeCorePlugin.getResourceString("SpecsBuilder.Reading_Specs"), 100); //$NON-NLS-1$
+		
+		try {
+			if (fCompileCommand != null) {
+				IConsole console = CCorePlugin.getDefault().getConsole("SPECS_BUILDER_CONSOLE_ID");
+				console.start(currentProject);
+				OutputStream cos = console.getOutputStream();
+
+				// Before launching give visual cues via the monitor
+				monitor.subTask(MakeCorePlugin.getResourceString("SpecsBuilder.Reading_Specs")); //$NON-NLS-1$
+				
+				String errMsg = null;
+				CommandLauncher launcher = new CommandLauncher();
+				// Print the command for visual interaction.
+				launcher.showCommand(true);
+
+				// add file and TSO
+				String[] compileArguments = prepareArguments(targetSpecificOptions);
+
+				String ca = coligate(compileArguments);
+
+				monitor.subTask(MakeCorePlugin.getResourceString("SpecsBuilder.Invoking_Command")
+						+ fCompileCommand.toString() + ca); //$NON-NLS-1$
+				cos = new StreamMonitor(new SubProgressMonitor(monitor, 70), cos, 100);
+				ErrorParserManager epm = new ErrorParserManager(currentProject, this, new String[] {SPECS_ERROR_PARSER});
+				epm.setOutputStream(cos);
+				OutputStream stdout = epm.getOutputStream();
+				OutputStream stderr = epm.getOutputStream();
+				Process p = launcher.execute(fCompileCommand, compileArguments, setEnvironment(launcher), workingDirectory);
+				if (p != null) {
+					try {
+						// Close the input of the Process explicitely.
+						// We will never write to it.
+						p.getOutputStream().close();
+					} catch (IOException e) {
+					}
+					if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor(monitor, 0))
+							!= CommandLauncher.OK)
+						errMsg = launcher.getErrorMessage();
+					monitor.subTask(MakeCorePlugin.getResourceString("SpecsBuilder.Parsing_Output")); //$NON-NLS-1$
+				}
+				else {
+					errMsg = launcher.getErrorMessage();
+				}
+
+				if (errMsg != null) {
+					String errorDesc = MakeCorePlugin.getFormattedString(BUILD_ERROR, 
+							fCompileCommand.toString() + ca);
+					epm.generateMarker(currentProject, -1, errorDesc, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
+				}
+
+				stdout.close();
+				stderr.close();
+
+				monitor.subTask(MakeCorePlugin.getResourceString("SpecsBuidler.Creating_Markers")); //$NON-NLS-1$
+				epm.reportProblems();
+				cos.close();
+			}
+		} catch (Exception e) {
+			CCorePlugin.log(e);
+		} finally {
+			monitor.done();
+		}
+		return true;
+	}
+
+	/**
+	 * @param tso
+	 * @return
+	 */
+	private String[] prepareArguments(String[] tso) {
+		String[] rv = null;
+		// commandArguments may have multiple arguments; tokenizing
+		int nTokens = 0;
+		if (fCompileArguments != null && fCompileArguments.length() > 0) {
+			StringTokenizer tokenizer = new StringTokenizer(fCompileArguments, " ");//$NON-NLS-1$
+			nTokens = tokenizer.countTokens();
+			if (nTokens > 0) {
+				rv = new String[nTokens + 1 + tso.length];
+				for (int i = 0; tokenizer.hasMoreTokens(); ++i) {
+					rv[i] = tokenizer.nextToken();
+				}
+			}
+		}
+		if (rv == null) {
+			rv = new String[1 + tso.length];
+		}
+		rv[nTokens] = targetFile;
+		for (int i = 0; i < tso.length; ++i) {
+			rv[nTokens + 1 + i] = tso[i];
+		}
+		return rv;
+	}
+
+	/**
+	 * @param array
+	 * @return
+	 */
+	private String coligate(String[] array) {
+		StringBuffer sb = new StringBuffer(128);
+		for (int i = 0; i < array.length; ++i) {
+			sb.append(' ');
+			sb.append(array[i]);
+		}
+		String ca = sb.toString();
+		return ca;
+	}
+
+	/**
+	 * @param launcher
+	 * @return
+	 */
+	private String[] setEnvironment(CommandLauncher launcher) {
+		// Set the environmennt, some scripts may need the CWD var to be set.
+		Properties props = launcher.getEnvironment();
+		props.put("CWD", workingDirectory.toOSString()); //$NON-NLS-1$
+		props.put("PWD", workingDirectory.toOSString()); //$NON-NLS-1$
+		String[] env = null;
+		ArrayList envList = new ArrayList();
+		Enumeration names = props.propertyNames();
+		if (names != null) {
+			while (names.hasMoreElements()) {
+				String key = (String) names.nextElement();
+				envList.add(key + "=" + props.getProperty(key)); //$NON-NLS-1$
+			}
+			env = (String[]) envList.toArray(new String[envList.size()]);
+		}
+		return env;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.IMarkerGenerator#addMarker(org.eclipse.core.resources.IResource, int, java.lang.String, int, java.lang.String)
+	 */
+	public void addMarker(IResource file, int lineNumber, String errorDesc, int severity, String errorVar) {
+		try {
+			IMarker[] cur = file.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_ONE);
+			/*
+			 * Try to find matching markers and don't put in duplicates
+			 */
+			if ((cur != null) && (cur.length > 0)) {
+				for (int i = 0; i < cur.length; i++) {
+					int line = ((Integer) cur[i].getAttribute(IMarker.LOCATION)).intValue();
+					int sev = ((Integer) cur[i].getAttribute(IMarker.SEVERITY)).intValue();
+					String mesg = (String) cur[i].getAttribute(IMarker.MESSAGE);
+					if (line == lineNumber && sev == mapMarkerSeverity(severity) && mesg.equals(errorDesc)) {
+						return;
+					}
+				}
+			}
+
+			IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER);
+			marker.setAttribute(IMarker.LOCATION, lineNumber);
+			marker.setAttribute(IMarker.MESSAGE, errorDesc);
+			marker.setAttribute(IMarker.SEVERITY, mapMarkerSeverity(severity));
+			marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+			marker.setAttribute(IMarker.CHAR_START, -1);
+			marker.setAttribute(IMarker.CHAR_END, -1);
+			if (errorVar != null) {
+				marker.setAttribute(ICModelMarker.C_MODEL_MARKER_VARIABLE, errorVar);
+			}
+		}
+		catch (CoreException e) {
+			CCorePlugin.log(e.getStatus());
+		}
+	}
+
+	int mapMarkerSeverity(int severity) {
+		switch (severity) {
+			case SEVERITY_ERROR_BUILD :
+			case SEVERITY_ERROR_RESOURCE :
+				return IMarker.SEVERITY_ERROR;
+			case SEVERITY_INFO :
+				return IMarker.SEVERITY_INFO;
+			case SEVERITY_WARNING :
+				return IMarker.SEVERITY_WARNING;
+		}
+		return IMarker.SEVERITY_ERROR;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,111 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.eclipse.cdt.core.CommandLauncher;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * TODO Provide description
+ * 
+ * @author vhirsl
+ */
+public class CygpathTranslator {
+	IProject project;
+	private String orgPath;
+	private String transPath;
+
+	public CygpathTranslator(IProject project, String path) {
+		this.project = project;
+		orgPath = path;
+	}
+	
+	public String run() {
+		ISafeRunnable runnable = new ISafeRunnable() {
+			public void run() throws Exception {
+				transPath = platformRun();
+			}
+
+			public void handleException(Throwable exception) {
+				transPath = orgPath;
+				MakeCorePlugin.log(exception);
+			}
+		};
+		Platform.run(runnable);
+		return transPath;
+	}
+
+	/**
+	 * @return
+	 */
+	private String platformRun() {
+		CommandLauncher launcher = new CommandLauncher();
+		launcher.showCommand(false);
+
+		OutputStream output = new ByteArrayOutputStream();
+
+		Process p = launcher.execute(
+			new Path("cygpath"),			//$NON-NLS-1$
+			new String[] {"-m", orgPath},	//$NON-NLS-1$
+			new String[0],//setEnvironment(launcher, "c:/"),//$NON-NLS-1$
+			new Path("."));				//$NON-NLS-1$
+		if (p != null) {
+			try {
+				// Close the input of the Process explicitely.
+				// We will never write to it.
+				p.getOutputStream().close();
+			}
+			catch (IOException e) {
+			}
+			if (launcher.waitAndRead(output, output) != CommandLauncher.OK) {
+				String errMsg = launcher.getErrorMessage();
+			}
+			else
+				return output.toString().trim();
+		}
+		return orgPath;
+	}
+
+	/**
+	 * @param launcher
+	 * @return
+	 */
+	private String[] setEnvironment(CommandLauncher launcher, String dir) {
+		// Set the environmennt, some scripts may need the CWD var to be set.
+		IPath workingDirectory = new Path(dir);
+		Properties props = launcher.getEnvironment();
+		props.put("CWD", workingDirectory.toOSString()); //$NON-NLS-1$
+		props.put("PWD", workingDirectory.toOSString()); //$NON-NLS-1$
+		String[] env = null;
+		ArrayList envList = new ArrayList();
+		Enumeration names = props.propertyNames();
+		if (names != null) {
+			while (names.hasMoreElements()) {
+				String key = (String) names.nextElement();
+				envList.add(key + "=" + props.getProperty(key)); //$NON-NLS-1$
+			}
+			env = (String[]) envList.toArray(new String[envList.size()]);
+		}
+		return env;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerConfigUtil.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerConfigUtil.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerConfigUtil.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerConfigUtil.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,96 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.core.scannerconfig.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class that handles some Scanner Config specifig collection conversions
+ * 
+ * @author vhirsl
+ */
+public final class ScannerConfigUtil {
+	
+	/**
+	 * Converts a map of symbols to a set
+	 * 
+	 * @param symbolsMap
+	 * @return
+	 */
+	public static Set scSymbolsMap2Set(Map symbolsMap) {
+		Set retSymbols = new HashSet();
+		Set keys = symbolsMap.keySet();
+		for (Iterator i = keys.iterator(); i.hasNext(); ) {
+			String symbol;
+			String key = (String) i.next();
+			String value = (String) symbolsMap.get(key);
+			if (value == null || value.length() == 0) {
+				symbol = key;
+			}
+			else {
+				symbol = key + "=" + value;	//$NON-NLS-1
+			}
+			retSymbols.add(symbol);
+		}
+		return retSymbols;
+	}
+
+	/**
+	 * Adds all new discovered symbols/values to the existing ones.
+	 *  
+	 * @param sumSymbols - a map of [String, Set] where Set is a SymbolEntry
+	 * @param symbols
+	 * @return boolean
+	 */
+	public static boolean scAddSymbolsSet2SymbolEntryMap(Map sumSymbols, Set symbols, boolean preferred) {
+		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) {
+				sEntry = new SymbolEntry(key, value, true);
+				rc = true;
+			}
+			else {
+				rc |= sEntry.add(value, preferred);
+			}
+			sumSymbols.put(key, sEntry);
+		}
+		return rc;
+	}
+
+	/**
+	 * Gets all discovered symbols with preferred values
+	 * @param sumSymbols
+	 * @return
+	 */
+	public static Set scSymbolsSymbolEntryMap2Set(Map sumSymbols) {
+		Set symbols = (Set) sumSymbols.entrySet();
+		Set rv = new HashSet(symbols.size());
+		for (Iterator i = symbols.iterator(); i.hasNext(); ) {
+			SymbolEntry sEntry = (SymbolEntry) ((Map.Entry) i.next()).getValue();
+			rv.add(sEntry.getPreferedRaw());
+		}
+		return rv;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/util/SymbolEntry.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,127 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.cdt.make.internal.core.scannerconfig.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+
+/**
+ * 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 Set values;
+	private String preferredValue;	// the first added value unless otherwise specified
+	
+	public SymbolEntry(String name) {
+		this.name = name;
+	}
+	public SymbolEntry(String name, String value) {
+		this(name);
+		if (values == null) {
+			values = new HashSet();
+		}
+		values.add(value);
+	}
+	public SymbolEntry(String name, String value, boolean preferred) {
+		this(name, value);
+		if (preferred) {
+			preferredValue = value;
+		}
+	}
+
+	public boolean add(String value) {
+		if (values == null) {
+			values = new HashSet();
+		}
+		if (preferredValue == null) {
+			preferredValue = value;
+		}
+		return values.add(value);
+	}
+	public boolean add(String value, boolean preferred) {
+		boolean rc = add(value);
+		if (preferred) {
+			preferredValue = value;
+		}
+		return rc;
+	}
+	public boolean addAll(SymbolEntry se) {
+		return values.addAll(se.values);
+	}
+	
+	public void removeAll() {
+		values = null;
+		preferredValue = null;
+	}
+	
+	public String getPrefered() {
+		return name+ "=" + (preferredValue == null ? UNSPECIFIED_VALUE : preferredValue);//$NON-NLS-1$
+	}
+	public String getPreferedRaw() {
+		return name + (preferredValue == null ? "" : "=" + preferredValue);//$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	public Set getAllButPreferred() {
+		if (values == null)
+			return null;
+		Set rv = new HashSet(values.size());
+		for (Iterator i = values.iterator(); i.hasNext(); ) {
+			String val = (String) i.next();
+			if (val.equals(preferredValue))
+				continue;
+			rv.add(name + "=" + (val == null ? UNSPECIFIED_VALUE : val));//$NON-NLS-1$
+		}
+		return rv;
+	}
+	public Set getAllButPreferredRaw() {
+		if (values == null)
+			return null;
+		Set rv = new HashSet(values.size());
+		for (Iterator i = values.iterator(); i.hasNext(); ) {
+			String val = (String) i.next();
+			if (val.equals(preferredValue))
+				continue;
+			rv.add(name + (val == null ? "" : "=" + val));//$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return rv;
+	}
+	public Set getAll() {
+		if (values == null)
+			return null;
+		Set rv = new HashSet(values.size());
+		for (Iterator i = values.iterator(); i.hasNext(); ) {
+			String val = (String) i.next();
+			rv.add(name + "=" + (val == null ? UNSPECIFIED_VALUE : val));//$NON-NLS-1$
+		}
+		return rv;
+	}
+	public Set getAllRaw() {
+		if (values == null)
+			return null;
+		Set rv = new HashSet(values.size());
+		for (Iterator i = values.iterator(); i.hasNext(); ) {
+			String val = (String) i.next();
+			rv.add(name + (val == null ? "" : "=" + val));//$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return rv;
+	}
+	
+}
Index: plugin.properties
===================================================================
retrieving revision 1.7
diff -u -r1.7 plugin.properties
--- plugin.properties	17 Oct 2003 02:34:10 -0000	1.7
+++ plugin.properties	19 Feb 2004 16:18:28 -0000
@@ -46,3 +46,5 @@
  
 MakefileEditor.name=Makefile Editor
 
+PropertyScannerConfig.name=Scanner Configuration Discovery
+PreferenceScannerConfig.name=Scanner Configuration Discovery
Index: plugin.xml
===================================================================
retrieving revision 1.26
diff -u -r1.26 plugin.xml
--- plugin.xml	2 Feb 2004 20:04:46 -0000	1.26
+++ plugin.xml	19 Feb 2004 16:18:28 -0000
@@ -399,5 +399,28 @@
          </actionSet>
       </perspectiveExtension>
    </extension>
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            adaptable="true"
+            objectClass="org.eclipse.core.resources.IProject"
+            name="%PropertyScannerConfig.name"
+            class="org.eclipse.cdt.make.internal.ui.properties.ScannerConfigPropertyPage"
+            id="org.eclipse.cdt.make.ui.properties.ScannerConfigPropertyPage">
+         <filter
+               name="nature"
+               value="org.eclipse.cdt.make.core.makeNature">
+         </filter>
+      </page>
+   </extension>
+   <extension
+         point="org.eclipse.ui.preferencePages">
+      <page
+            name="%PreferenceScannerConfig.name"
+            category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
+            class="org.eclipse.cdt.make.internal.ui.preferences.ScannerConfigPreferencePage"
+            id="org.eclipse.cdt.make.ui.preferences.ScannerConfigPreferencePage">
+      </page>
+   </extension>
 
 </plugin>
Index: src/org/eclipse/cdt/make/internal/ui/MakeResources.properties
===================================================================
retrieving revision 1.9
diff -u -r1.9 MakeResources.properties
--- src/org/eclipse/cdt/make/internal/ui/MakeResources.properties	13 Jan 2004 18:54:39 -0000	1.9
+++ src/org/eclipse/cdt/make/internal/ui/MakeResources.properties	19 Feb 2004 16:18:30 -0000
@@ -102,3 +102,11 @@
 LexicalSortingAction.tooltip.on=Do Not Sort
 LexicalSortingAction.tooltip.off=Sort
 
+# --- ScannerConfigPage ---
+ScannerConfigPage.label=Scanner Config
+ScannerConfigPage.desc=Scanner configuration discovery settings
+ScannerConfigPage.activate=Automate scanner configuration discovery
+
+ScannerConfigPage.specsCmd.group_label=Generate specs command
+ScannerConfigPage.specsCmd.use_default=Use default
+ScannerConfigPage.specsCmd.label=Generate specs command:
Index: src/org/eclipse/cdt/make/ui/dialogs/SettingsBlock.java
===================================================================
retrieving revision 1.4
diff -u -r1.4 SettingsBlock.java
--- src/org/eclipse/cdt/make/ui/dialogs/SettingsBlock.java	13 Jan 2004 18:54:39 -0000	1.4
+++ src/org/eclipse/cdt/make/ui/dialogs/SettingsBlock.java	19 Feb 2004 16:18:30 -0000
@@ -91,6 +91,7 @@
 		if (fBuildInfo.isStopOnError()) {
 			stopOnErrorButton.setSelection(true);
 		}
+		stopOnErrorButton.setEnabled(fBuildInfo.isDefaultBuildCmd());
 	}
 
 	protected void createBuildCmdControls(Composite parent) {
@@ -142,8 +143,6 @@
 		}
 		if (fBuildInfo.isDefaultBuildCmd()) {
 			buildCommand.setEnabled(false);
-		} else {
-			stopOnErrorButton.setEnabled(false);
 		}
 		defButton.setSelection(fBuildInfo.isDefaultBuildCmd());
 	}
Index: src/org/eclipse/cdt/make/ui/wizards/MakeProjectWizardOptionPage.java
===================================================================
retrieving revision 1.7
diff -u -r1.7 MakeProjectWizardOptionPage.java
--- src/org/eclipse/cdt/make/ui/wizards/MakeProjectWizardOptionPage.java	14 Oct 2003 20:59:08 -0000	1.7
+++ src/org/eclipse/cdt/make/ui/wizards/MakeProjectWizardOptionPage.java	19 Feb 2004 16:18:30 -0000
@@ -5,8 +5,9 @@
  * All Rights Reserved.
  */
 
+import org.eclipse.cdt.make.core.MakeCorePlugin;
 import org.eclipse.cdt.make.internal.ui.MakeProjectOptionBlock;
-import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
+import org.eclipse.cdt.make.ui.dialogs.ScannerConfigPage;
 import org.eclipse.cdt.ui.dialogs.ICOptionContainer;
 import org.eclipse.cdt.ui.dialogs.ReferenceBlock;
 import org.eclipse.cdt.ui.dialogs.TabFolderOptionBlock;
@@ -40,6 +41,7 @@
 		protected void addTabs() {
 			addTab(new ReferenceBlock());
 			super.addTabs();
+			addTab(new ScannerConfigPage());
 		}
 	}
 
@@ -61,7 +63,7 @@
 	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#getPreference()
 	 */
 	public Preferences getPreferences() {
-		return MakeUIPlugin.getDefault().getPluginPreferences();
+		return MakeCorePlugin.getDefault().getPluginPreferences();
 	}
 
 }
Index: src/org/eclipse/cdt/make/internal/ui/preferences/ScannerConfigPreferencePage.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/ui/preferences/ScannerConfigPreferencePage.java
diff -N src/org/eclipse/cdt/make/internal/ui/preferences/ScannerConfigPreferencePage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/ui/preferences/ScannerConfigPreferencePage.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,91 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.ui.preferences;
+
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.cdt.ui.dialogs.ICOptionContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.ui.dialogs.ScannerConfigPage;
+
+/**
+ * TODO: Provide description for "ScannerConfigPreferencePage".
+ * @see PreferencePage
+ */
+public class ScannerConfigPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, ICOptionContainer {
+
+	private ScannerConfigPage fScannerConfigPage;
+	
+	public ScannerConfigPreferencePage() {
+		super();
+	}
+
+	/**
+	 * @see PreferencePage#init
+	 */
+	public void init(IWorkbench workbench)  {
+	}
+
+	/**
+	 * @see PreferencePage#createContents
+	 */
+	protected Control createContents(Composite parent)  {
+		fScannerConfigPage = new ScannerConfigPage(true);	// add title
+		// must set container before call to createControl
+		fScannerConfigPage.setContainer(this);
+		
+		fScannerConfigPage.createControl(parent);
+		return fScannerConfigPage.getControl();
+	}
+
+	protected void performDefaults() {
+		fScannerConfigPage.performDefaults();
+		super.performDefaults();
+	}
+	
+	public boolean performOk() {
+		try {
+			fScannerConfigPage.performApply(null);
+			MakeCorePlugin.getDefault().savePluginPreferences();
+			return true;
+		} 
+		catch (CoreException e) {
+			return false;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#updateContainer()
+	 */
+	public void updateContainer() {
+		setErrorMessage(fScannerConfigPage.getErrorMessage());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#getProject()
+	 */
+	public IProject getProject() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#getPreferences()
+	 */
+	public Preferences getPreferences() {
+		return MakeCorePlugin.getDefault().getPluginPreferences();
+	}
+}
Index: src/org/eclipse/cdt/make/internal/ui/properties/ScannerConfigPropertyPage.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/ui/properties/ScannerConfigPropertyPage.java
diff -N src/org/eclipse/cdt/make/internal/ui/properties/ScannerConfigPropertyPage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/ui/properties/ScannerConfigPropertyPage.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,79 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.internal.ui.properties;
+
+import org.eclipse.cdt.ui.dialogs.ICOptionContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.ui.dialogs.ScannerConfigPage;
+
+public class ScannerConfigPropertyPage extends PropertyPage implements ICOptionContainer {
+
+	private ScannerConfigPage fScannerConfigPage;
+
+	public ScannerConfigPropertyPage() {
+		super();
+	}
+
+	/**
+	 * @see PreferencePage#createContents(Composite)
+	 */
+	protected Control createContents(Composite parent) {
+		fScannerConfigPage = new ScannerConfigPage(true);	// add title
+		// must set container before call to createControl
+		fScannerConfigPage.setContainer(this);
+		
+		fScannerConfigPage.createControl(parent);
+		return fScannerConfigPage.getControl();
+	}
+
+	protected void performDefaults() {
+		fScannerConfigPage.performDefaults();
+		super.performDefaults();
+	}
+	
+	public boolean performOk() {
+		try {
+			fScannerConfigPage.performApply(null);
+			return true;
+		}
+		catch (CoreException e) {
+			return false;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#updateContainer()
+	 */
+	public void updateContainer() {
+		setErrorMessage(fScannerConfigPage.getErrorMessage());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#getProject()
+	 */
+	public IProject getProject() {
+		return (IProject) getElement();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#getPreferences()
+	 */
+	public Preferences getPreferences() {
+		return MakeCorePlugin.getDefault().getPluginPreferences();
+	}
+
+}
Index: src/org/eclipse/cdt/make/ui/dialogs/ScannerConfigPage.java
===================================================================
RCS file: src/org/eclipse/cdt/make/ui/dialogs/ScannerConfigPage.java
diff -N src/org/eclipse/cdt/make/ui/dialogs/ScannerConfigPage.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/ui/dialogs/ScannerConfigPage.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,277 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.cdt.make.ui.dialogs;
+
+import org.eclipse.cdt.ui.dialogs.AbstractCOptionPage;
+import org.eclipse.cdt.ui.dialogs.ICOptionContainer;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigNature;
+import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
+
+/**
+ *
+ * @author vhirsl
+ */
+public class ScannerConfigPage extends AbstractCOptionPage {
+	private static final String PREFIX = "ScannerConfigPage";	//$NON-NLS-1$
+	private static final String LABEL = PREFIX + ".label";	//$NON-NLS-1$
+	private static final String DESC = PREFIX + ".desc";	//$NON-NLS-1$
+	private static final String ACTIVATE_AUTO_DISCOVERY = PREFIX + ".activate"; //$NON-NLS-1$
+	private static final String SPECS_CMD_GROUP = PREFIX + ".specsCmd.group_label"; //$NON-NLS-1$
+	private static final String SPECS_CMD_USE_DEFAULT = PREFIX + ".specsCmd.use_default"; //$NON-NLS-1$
+	private static final String SPECS_CMD_LABEL = PREFIX + ".specsCmd.label"; //$NON-NLS-1$
+
+	
+	private boolean addTitle = false;
+
+	private Button autoDiscovery;
+
+	Button defButton;
+	Text specsCommand;
+	
+	IScannerConfigBuilderInfo fBuildInfo;
+	
+	/**
+	 * Default constructor
+	 */
+	public ScannerConfigPage() {
+		super(MakeUIPlugin.getResourceString(LABEL));
+		setDescription(MakeUIPlugin.getResourceString(DESC));
+	}
+
+	/**
+	 * @param addTitle
+	 */
+	public ScannerConfigPage(boolean addTitle) {
+		this();
+		this.addTitle = addTitle;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionPage#setContainer(org.eclipse.cdt.ui.dialogs.ICOptionContainer)
+	 */
+	public void setContainer(ICOptionContainer container) {
+		super.setContainer(container);
+		IProject project = container.getProject();
+		if (project != null) {
+			try {
+				fBuildInfo = MakeCorePlugin.createScannerConfigBuildInfo(project, ScannerConfigBuilder.BUILDER_ID);
+			}
+			catch (CoreException e) {
+				fBuildInfo = MakeCorePlugin.createScannerConfigBuildInfo(container.getPreferences(), ScannerConfigBuilder.BUILDER_ID, true);
+			}
+		}
+		else {
+			fBuildInfo = MakeCorePlugin.createScannerConfigBuildInfo(container.getPreferences(), ScannerConfigBuilder.BUILDER_ID, false);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt..dialogs.ICOptionPage#performApply(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void performApply(IProgressMonitor monitor) throws CoreException {
+		// install/deinstall the scanner configuration builder
+		IProject project = getContainer().getProject();
+		IScannerConfigBuilderInfo buildInfo;
+		if (project != null) {
+			if (autoDiscovery.getSelection()) {
+				ScannerConfigNature.addScannerConfigNature(project);
+				buildInfo = MakeCorePlugin.createScannerConfigBuildInfo(project, ScannerConfigBuilder.BUILDER_ID);
+				buildInfo.setAutoDiscoveryEnabled(autoDiscovery.getSelection());
+			}
+			else {
+				ScannerConfigNature.removeScannerConfigNature(project);
+				return;
+			}
+		}
+		else {
+			buildInfo = MakeCorePlugin.createScannerConfigBuildInfo(getContainer().getPreferences(), ScannerConfigBuilder.BUILDER_ID, false);
+			buildInfo.setAutoDiscoveryEnabled(autoDiscovery.getSelection());
+		}
+		buildInfo.setUseDefaultSpecsCmd(useDefaultSpecsCmd());
+		if (!useDefaultSpecsCmd()) {
+			String specsLine = getSpecsCommandLine();
+			int start = 0;
+			int end = -1;
+			if (specsLine.startsWith("\"")) { //$NON-NLS-1$
+				start = 1;
+				end = specsLine.indexOf('"', 1);
+			}
+			else {
+				end = specsLine.indexOf(' ');
+			}
+			IPath path;
+			if (end == -1) {
+				path = new Path(specsLine);
+			} else {
+				path = new Path(specsLine.substring(start, end));
+			}
+			buildInfo.setSpecsCommand(path);
+			String args = ""; //$NON-NLS-1$
+			if (end != -1) {
+				args = specsLine.substring(end + 1);
+			}
+			buildInfo.setSpecsArguments(args);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performDefaults()
+	 */
+	public void performDefaults() {
+		IScannerConfigBuilderInfo buildInfo;
+		// Populate with the default value
+		if (getContainer().getProject() != null) {
+			// get the preferences
+			buildInfo = MakeCorePlugin.createScannerConfigBuildInfo(getContainer().getPreferences(),
+					ScannerConfigBuilder.BUILDER_ID, false);
+		}
+		else {
+			// get the defaults
+			buildInfo = MakeCorePlugin.createScannerConfigBuildInfo(getContainer().getPreferences(),
+					ScannerConfigBuilder.BUILDER_ID, true);
+		}
+		autoDiscovery.setSelection(buildInfo.isAutoDiscoveryEnabled());
+		IPath sCommand = fBuildInfo.getSpecsCommand();
+		if (sCommand != null) {
+			StringBuffer cmd = new StringBuffer(sCommand.toOSString());
+			String args = buildInfo.getSpecsArguments();
+			if (args != null && !args.equals("")) { //$NON-NLS-1$
+				cmd.append(' ');
+				cmd.append(args);
+			}
+			specsCommand.setText(cmd.toString());
+		}
+		if (buildInfo.isDefaultSpecsCmd()) {
+			specsCommand.setEnabled(false);
+		} else {
+			specsCommand.setEnabled(true);
+		}
+		defButton.setSelection(buildInfo.isDefaultSpecsCmd());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite composite = ControlFactory.createComposite(parent, 1);
+		setControl(composite);
+
+		if (addTitle) {
+			addTitle(composite);
+		}
+		addSCDiscoveryState(composite);
+//		addSeparator(composite);
+		createSpecsCmdControls(composite);
+	}
+
+	private void addTitle(Composite composite) {
+		//Label for dialog title
+		Label pathLabel = ControlFactory.createLabel(composite, MakeUIPlugin.getResourceString(DESC));
+	}
+	
+	private void addSCDiscoveryState(Composite parent) {
+		//Checkbox for enabling the discovery
+		ControlFactory.insertSpace(parent, 1, 10);
+		autoDiscovery = ControlFactory.createCheckBox(parent, MakeUIPlugin.getResourceString(ACTIVATE_AUTO_DISCOVERY));
+		autoDiscovery.setSelection(fBuildInfo.isAutoDiscoveryEnabled());
+	}
+
+	private void addSeparator(Composite parent) {
+		Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+		GridData gridData = new GridData();
+		gridData.horizontalAlignment = GridData.FILL;
+		gridData.grabExcessHorizontalSpace = true;
+		separator.setLayoutData(gridData);
+	}
+
+	private void createSpecsCmdControls(Composite parent) {
+		Group group = ControlFactory.createGroup(parent, MakeUIPlugin.getResourceString(SPECS_CMD_GROUP), 2);
+		defButton = ControlFactory.createCheckBox(group, MakeUIPlugin.getResourceString(SPECS_CMD_USE_DEFAULT));
+		defButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (useDefaultSpecsCmd() == true) {
+					specsCommand.setEnabled(false);
+				} else {
+					specsCommand.setEnabled(true);
+				}
+				getContainer().updateContainer();
+			}
+		});
+		((GridData) (defButton.getLayoutData())).horizontalAlignment = GridData.FILL_HORIZONTAL;
+		((GridData) (defButton.getLayoutData())).horizontalSpan = 2;
+		Label label = ControlFactory.createLabel(group, MakeUIPlugin.getResourceString(SPECS_CMD_LABEL));
+		((GridData) (label.getLayoutData())).horizontalAlignment = GridData.BEGINNING;
+		((GridData) (label.getLayoutData())).grabExcessHorizontalSpace = false;
+		specsCommand = ControlFactory.createTextField(group, SWT.SINGLE | SWT.BORDER);
+		((GridData) (specsCommand.getLayoutData())).horizontalAlignment = GridData.FILL;
+		((GridData) (specsCommand.getLayoutData())).grabExcessHorizontalSpace = true;
+		specsCommand.addListener(SWT.Modify, new Listener() {
+			public void handleEvent(Event e) {
+				getContainer().updateContainer();
+			}
+		});
+		IPath sCommand = fBuildInfo.getSpecsCommand();
+		if (sCommand != null) {
+			StringBuffer cmd = new StringBuffer(sCommand.toOSString());
+			String args = fBuildInfo.getSpecsArguments();
+			if (args != null && !args.equals("")) { //$NON-NLS-1$
+				cmd.append(' ');
+				cmd.append(args);
+			}
+			specsCommand.setText(cmd.toString());
+		}
+		if (fBuildInfo.isDefaultSpecsCmd()) {
+			specsCommand.setEnabled(false);
+		}
+		defButton.setSelection(fBuildInfo.isDefaultSpecsCmd());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#getErrorMessage()
+	 */
+	public String getErrorMessage() {
+		if (!useDefaultSpecsCmd()) {
+			String cmd = getSpecsCommandLine();
+			if (cmd == null || cmd.length() == 0) {
+				return "Must enter a 'specs' command";	//$NON-NLS-1$
+			}
+		}
+		return null;
+	}
+
+	private boolean useDefaultSpecsCmd() {
+		return defButton.getSelection();
+	}
+
+	private String getSpecsCommandLine() {
+		return specsCommand.getText().trim();
+	}
+}

Back to the top