Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Fw: CDT2.0 Scanner configuration discovery

This patch contains redesigned implementation of Scanner config discovery. 
After Doug's inspections following changes were made:
- ErrorParserManager, IErrorParser interface and ErrorParsers extension 
point are not used anymore. Instead, ScannerInfoConsoleParser extension 
point is defined with appropriate surrounding classes.
- GNU specifics are now minimized to two ScannerInfoConsoleParsers one for 
make builder, the other for ExternalScannerInforProvider command 
(implemented as extension point/extension) and a cygpath translator.
- The build/error parse performance is not affected in case console 
parsing for scanner info is disabled.
- New Scanner config page for Preferences, project properties and New Make 
Project wizard.

Limitations/future work: 
- relative paths are not handled properly yet, currently being worked on,
- changes to Paths and Symbols page UI to follow.

Please let me know if the work can be further improved, I am eager to see 
it in CVS.

Thanks,
Vmir

P.S. Huge thanks to Doug for many valuable comments.

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	4 Mar 2004 21:38:44 -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
+
+epScannerConfigNature.name=Scanner Configuration Nature
+epScannerConfigBuilder.name=Scanner Configuration Builder
+extensionExternalScannerInfoProvider.name=C/C++ External Scanner Info Provider Extension
+epDefaultExternalScannerInfoProvider.name=Default External Scanner Info Provider
+
+extensionScannerInfoConsoleParser.name=C/C++ Scanner Info Console Parser Extension
+epGCCCommandLineParser.name=GNU C/C++ Scanner Info Parser
+epGCCSpecsParser.name=GNU C/C++ Compiler Specs Parser
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	4 Mar 2004 21:38:44 -0000
@@ -21,6 +21,8 @@
 
 
    <extension-point id="MakeTargetBuilder" name="%extensionTargetBuilder.name" schema="schema/MakeTargetBuilder.exsd"/>
+   <extension-point id="ExternalScannerInfoProvider" name="%extensionExternalScannerInfoProvider.name" schema="schema/ExternalScannerInfoProvider.exsd"/>
+   <extension-point id="ScannerInfoConsoleParser" name="%extensionScannerInfoConsoleParser.name" schema="schema/ScannerInfoConsoleParser.exsd"/>
 
    <extension
          id="MakeScannerProvider"
@@ -76,6 +78,69 @@
             builderID="org.eclipse.cdt.make.core.makeBuilder"
             id="org.eclipse.cdt.make.MakeTargetBuilder">
       </builder>
+   </extension>
+   <extension
+         id="ScannerConfigNature"
+         name="%epScannerConfigNature.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="%epScannerConfigBuilder.name"
+         point="org.eclipse.core.resources.builders">
+      <builder
+            hasNature="true">
+         <run
+               class="org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder">
+         </run>
+      </builder>
+   </extension>
+   <extension
+         id="DefaultExternalScannerInfoProvider"
+         name="%epDefaultExternalScannerInfoProvider.name"
+         point="org.eclipse.cdt.make.core.ExternalScannerInfoProvider">
+      <externalScannerInfoProvider>
+         <run
+               class="org.eclipse.cdt.make.internal.core.scannerconfig.DefaultExternalScannerInfoProvider">
+            <parameter
+                  name="defaultCommand"
+                  value="gcc">
+            </parameter>
+            <parameter
+                  name="defaultAttributes"
+                  value="-c -v">
+            </parameter>
+         </run>
+      </externalScannerInfoProvider>
+   </extension>
+   <extension
+         id="GCCScannerInfoConsoleParser"
+         name="%epGCCCommandLineParser.name"
+         point="org.eclipse.cdt.make.core.ScannerInfoConsoleParser">
+      <scannerInfoConsoleParser
+            commandId="makeBuilder"
+            class="org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCScannerInfoConsoleParser">
+      </scannerInfoConsoleParser>
+   </extension>
+   <extension
+         id="GCCSpecsConsoleParser"
+         name="%epGCCSpecsParser.name"
+         point="org.eclipse.cdt.make.core.ScannerInfoConsoleParser">
+      <scannerInfoConsoleParser
+            commandId="externalScannerInfoProvider"
+            class="org.eclipse.cdt.make.internal.core.scannerconfig.gnu.GCCSpecsConsoleParser">
+      </scannerInfoConsoleParser>
    </extension>
 
 </plugin>
Index: src/org/eclipse/cdt/make/core/MakeBuilder.java
===================================================================
retrieving revision 1.18
diff -u -r1.18 MakeBuilder.java
--- src/org/eclipse/cdt/make/core/MakeBuilder.java	24 Feb 2004 02:03:08 -0000	1.18
+++ src/org/eclipse/cdt/make/core/MakeBuilder.java	4 Mar 2004 21:38:44 -0000
@@ -24,6 +24,7 @@
 import org.eclipse.cdt.core.resources.ACBuilder;
 import org.eclipse.cdt.core.resources.IConsole;
 import org.eclipse.cdt.make.internal.core.StreamMonitor;
+import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoConsoleParserFactory;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
@@ -179,6 +180,9 @@
 				epm.setOutputStream(streamMon);
 				OutputStream stdout = epm.getOutputStream();
 				OutputStream stderr = epm.getOutputStream();
+				// Sniff console output for scanner info
+				OutputStream sniffer = ScannerInfoConsoleParserFactory.getMakeBuilderOutputSniffer(
+						epm.getOutputStream(), getProject(), workingDirectory, this);
 				Process p = launcher.execute(buildCommand, buildArguments, env, workingDirectory);
 				if (p != null) {
 					try {
@@ -189,7 +193,7 @@
 					}
 					// Before launching give visual cues via the monitor
 					monitor.subTask(MakeCorePlugin.getResourceString("MakeBuilder.Invoking_Command") + launcher.getCommandLine()); //$NON-NLS-1$
-					if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor(monitor, 0))
+					if (launcher.waitAndRead(sniffer, sniffer, new SubProgressMonitor(monitor, 0))
 						!= CommandLauncher.OK)
 						errMsg = launcher.getErrorMessage();
 					monitor.subTask(MakeCorePlugin.getResourceString("MakeBuilder.Updating_project")); //$NON-NLS-1$
@@ -225,6 +229,7 @@
 				stderr.close();
 
 				monitor.subTask(MakeCorePlugin.getResourceString("MakeBuilder.Creating_Markers")); //$NON-NLS-1$
+				sniffer.close();
 				epm.reportProblems();
 				cos.close();
 			}
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	4 Mar 2004 21:38:44 -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
@@ -13,19 +13,30 @@
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 
 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.IExternalScannerInfoProvider;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser;
+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 +51,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 EXTERNAL_SI_PROVIDER_SIMPLE_ID = "ExternalScannerInfoProvider"; //$NON-NLS-1$
+	public static final String SI_CONSOLE_PARSER_SIMPLE_ID = "ScannerInfoConsoleParser";	//$NON-NLS-1$
+	public static final String DEFAULT_EXTERNAL_SI_PROVIDER_ID = MakeCorePlugin.getUniqueIdentifier() + ".DefaultExternalScannerInfoProvider"; //$NON-NLS-1$
+	public static final String GCC_SPECS_CONSOLE_PARSER_ID = MakeCorePlugin.getUniqueIdentifier() + ".GCCSpecsConsoleParser"; //$NON-NLS-1$
+	public static final String GCC_SCANNER_INFO_CONSOLE_PARSER_ID = MakeCorePlugin.getUniqueIdentifier() + ".GCCScannerInfoConsoleParser"; //$NON-NLS-1$
+	
 	//The shared instance.
 	private static MakeCorePlugin plugin;
 	//Resource bundle.
@@ -131,6 +149,20 @@
 		} 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.setUseDefaultESIProviderCmd(true);
+			scInfo.setESIProviderCommand(new Path("gcc")); //$NON-NLS-1$
+			scInfo.setESIProviderArguments("-c -v");	//$NON-NLS-1$
+			scInfo.setESIProviderConsoleParserId(GCC_SPECS_CONSOLE_PARSER_ID);
+			scInfo.setMakeBuilderConsoleParserId(GCC_SCANNER_INFO_CONSOLE_PARSER_ID);
+			scInfo.setMakeBuilderConsoleParserEnabled(true);
+			scInfo.setESIProviderConsoleParserEnabled(true);
+		} catch (CoreException e) {
+		}
 	}
 	
 	public static IMakeBuilderInfo createBuildInfo(Preferences prefs, String builderID, boolean useDefaults) {
@@ -179,4 +211,109 @@
 		}
 	}
 
+	/*
+	 * 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();
+	}
+
+	/**
+	 * @param id - id specifying external scanner info provider
+	 * @return provider - new instance of an external scanner info provider
+	 */
+	public IExternalScannerInfoProvider getExternalScannerInfoProvider(String id) {
+		try {
+			IExtensionPoint extension = getDescriptor().getExtensionPoint(EXTERNAL_SI_PROVIDER_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) { 
+								IExternalScannerInfoProvider builder = (IExternalScannerInfoProvider) runElement[0].createExecutableExtension("class");
+								return builder;
+							}
+						}
+					}
+				}
+			}
+		} 
+		catch (CoreException e) {
+			log(e);
+		}
+		return null;
+	}
+
+	/**
+	 * @param commandId
+	 * @return String[] - array of parserIds associated with the commandId or 'all'
+	 */
+	public String[] getScannerInfoConsoleParserIds(String commandId) {
+		String[] empty = new String[0];
+		if (commandId == null || commandId.length() == 0) {
+			commandId = "all";	//$NON-NLS-1$
+		}
+		IExtensionPoint extension = getDescriptor().getExtensionPoint(SI_CONSOLE_PARSER_SIMPLE_ID);
+		if (extension != null) {
+			IExtension[] extensions = extension.getExtensions();
+			List parserIds = new ArrayList(extensions.length);
+			for (int i = 0; i < extensions.length; i++) {
+				String parserId = extensions[i].getUniqueIdentifier();
+				if (parserId != null) {
+					IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+					String id = configElements[0].getAttribute("commandId");//$NON-NLS-1$
+					if (id != null && (id.equals(commandId) || id.equals("all"))) {	//$NON-NLS-1$
+						parserIds.add(parserId);
+					}
+				}							
+			}
+			return (String[])parserIds.toArray(empty);
+		}
+		return empty;
+	}
+	
+	/**
+	 * @param parserId
+	 * @return parser - parser object identified by the parserId
+	 */
+	public IScannerInfoConsoleParser getScannerInfoConsoleParser(String parserId) {
+		try {
+			IExtensionPoint extension = getDescriptor().getExtensionPoint(SI_CONSOLE_PARSER_SIMPLE_ID);
+			if (extension != null) {
+				IExtension[] extensions = extension.getExtensions();
+				for (int i = 0; i < extensions.length; i++) {
+					String id = extensions[i].getUniqueIdentifier();
+					if (id != null && id.equals(parserId)) {
+						IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+						IScannerInfoConsoleParser parser = (IScannerInfoConsoleParser)configElements[0].createExecutableExtension("class");//$NON-NLS-1$
+						return parser;
+					}
+				}
+			}
+		}
+		catch (CoreException e) {
+			log(e);
+		}
+		return null;
+	}
 }
Index: src/org/eclipse/cdt/make/core/PluginResources.properties
===================================================================
retrieving revision 1.6
diff -u -r1.6 PluginResources.properties
--- src/org/eclipse/cdt/make/core/PluginResources.properties	2 Mar 2004 17:13:52 -0000	1.6
+++ src/org/eclipse/cdt/make/core/PluginResources.properties	4 Mar 2004 21:38:44 -0000
@@ -13,4 +13,17 @@
 MakeTargetManager.failed_initializing_targets=Failed initializing build targets
 MakeTargetManager.error_writing_file=Error writing target file
 
-ProjectTargets.error_reading_project_targets=Error reading project targets.
\ No newline at end of file
+ProjectTargets.error_reading_project_targets=Error reading project targets.
+
+ScannerConfigBuilder.Invoking_Builder=Invoking scanner config builder on project 
+
+ExternalScannerInfoProvider.Provider_Error=Error launching compiler scanner info generator ({0})
+ExternalScannerInfoProvider.Reading_Specs=Reading specs ... 
+ExternalScannerInfoProvider.Invoking_Command=Invoking Command: 
+ExternalScannerInfoProvider.Parsing_Output=Parsing output ... 
+ExternalScannerInfoProvider.Creating_Markers=Generating markers ... 
+
+ScannerInfoCollector.Processing=Processing discovered scanner configuration ... 
+ScannerInfoCollector.Updating=Updating Scanner Configuration for project 
+
+GCCScannerConfigUtil.Error_Message=Error creating specs file
Index: schema/ExternalScannerInfoProvider.exsd
===================================================================
RCS file: schema/ExternalScannerInfoProvider.exsd
diff -N schema/ExternalScannerInfoProvider.exsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ schema/ExternalScannerInfoProvider.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="ExternalScannerInfoProvider" name="C/C++ Scanner Info Provider"/>
+      </appInfo>
+      <documentation>
+         This extension point is used to plug in particular compiler scanner info provider.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="externalScannerInfoProvider" 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="externalScannerInfoProvider">
+      <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.ICompilerScannerInfoProvider&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 compiler scanner info provider.
+         </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.IExternalScannerInfoProvider&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 scanner info provider.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
Index: schema/ScannerInfoConsoleParser.exsd
===================================================================
RCS file: schema/ScannerInfoConsoleParser.exsd
diff -N schema/ScannerInfoConsoleParser.exsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ schema/ScannerInfoConsoleParser.exsd	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,119 @@
+<?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="ScannerInfoConsoleParser" name="%extensionScannerInfoConsoleParser.name"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="scannerInfoConsoleParser"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="scannerInfoConsoleParser">
+      <complexType>
+         <attribute name="commandId" use="default" value="all">
+            <annotation>
+               <documentation>
+                  Id of the command the console parser is associated with. Can be &apos;all&apos;, &apos;makeBuilder&apos; or &apos;externalScannerInfoProvider&apos;.
+               </documentation>
+            </annotation>
+            <simpleType>
+               <restriction base="string">
+                  <enumeration value="all">
+                  </enumeration>
+                  <enumeration value="makeBuilder">
+                  </enumeration>
+                  <enumeration value="externalScannerInfoProvider">
+                  </enumeration>
+               </restriction>
+            </simpleType>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Java class that implements IScannerInfoConsoleParser interface.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.cdt.make.core.IScannerInfoConsoleParser"/>
+               </appInfo>
+            </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>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
Index: src/org/eclipse/cdt/make/core/scannerconfig/IExternalScannerInfoProvider.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/IExternalScannerInfoProvider.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/IExternalScannerInfoProvider.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/IExternalScannerInfoProvider.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * 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.IProgressMonitor;
+
+/**
+ * Interface for providers of C/C++ scanner info 
+ * 
+ * @author vhirsl
+ */
+public interface IExternalScannerInfoProvider {
+	/**
+	 * Invokes a C/C++ compiler with target specific options to generate
+	 * compiler scanner info.
+	 * 
+	 * @param monitor
+	 * @param current project - current project being built
+	 * @param buildInfo - settings for ScannerConfigBuilder
+	 * @param targetSpecificOptions - array of options affecting compiler specs
+	 */
+	public boolean invokeProvider(IProgressMonitor monitor, 
+								  IProject currentProject,
+								  IScannerConfigBuilderInfo buildInfo, 
+								  String[] targetSpecificOptions); 
+}
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,46 @@
+/**********************************************************************
+ * 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 isDefaultESIProviderCmd();
+	void setUseDefaultESIProviderCmd(boolean on) throws CoreException;
+
+	IPath getESIProviderCommand();
+	void setESIProviderCommand(IPath command) throws CoreException;
+
+	String getESIProviderArguments();
+	void setESIProviderArguments(String args) throws CoreException;
+
+	String getESIProviderConsoleParserId();
+	void setESIProviderConsoleParserId(String parserId) throws CoreException;
+
+	String getMakeBuilderConsoleParserId();
+	void setMakeBuilderConsoleParserId(String parserId) throws CoreException;
+
+	boolean isMakeBuilderConsoleParserEnabled();
+	void setMakeBuilderConsoleParserEnabled(boolean enabled) throws CoreException;
+
+	boolean isESIProviderConsoleParserEnabled();
+	void setESIProviderConsoleParserEnabled(boolean enabled) throws CoreException;
+}
Index: src/org/eclipse/cdt/make/core/scannerconfig/IScannerInfoConsoleParser.java
===================================================================
RCS file: src/org/eclipse/cdt/make/core/scannerconfig/IScannerInfoConsoleParser.java
diff -N src/org/eclipse/cdt/make/core/scannerconfig/IScannerInfoConsoleParser.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/core/scannerconfig/IScannerInfoConsoleParser.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.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Parses a line of command output looking for scanner info entries.
+ * 
+ * @author vhirsl
+ */
+public interface IScannerInfoConsoleParser {
+	/**
+	 * Optional one time initialization of a console parser.
+	 * 
+	 * @param project
+	 */
+	public void startup(IProject project, IScannerInfoConsoleParserUtility util);
+	
+	/**
+	 * Parse one line of output.
+	 * @param line
+	 * @return true if scanner info entry was found in the line
+	 */
+	public boolean processLine(String line);
+	
+	/**
+	 * Optional finalization of a console parser.
+	 */
+	public void shutdown();
+}
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$
+		monitor.subTask(MakeCorePlugin.getResourceString("ScannerConfigBuilder.Invoking_Builder") +	//$NON-NLS-1$ 
+				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,128 @@
+/**********************************************************************
+ * 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;
+	}
+	
+	public static 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);
+	}
+	
+	public static 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/ConsoleOutputStreamSniffer.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/ConsoleOutputStreamSniffer.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/ConsoleOutputStreamSniffer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/ConsoleOutputStreamSniffer.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,117 @@
+/**********************************************************************
+ * 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.io.IOException;
+import java.io.OutputStream;
+
+import org.eclipse.cdt.make.core.scannerconfig.*;
+
+/**
+ * Intercepts an output to console and forwards it to line parsers for processing
+ * 
+ * @author vhirsl
+ */
+public class ConsoleOutputStreamSniffer extends OutputStream {
+
+	private StringBuffer currentLine = new StringBuffer();
+	private OutputStream outputStream;
+	private int nOpens = 0;
+	private IScannerInfoConsoleParser[] parsers;
+	
+	public ConsoleOutputStreamSniffer(IScannerInfoConsoleParser[] parsers) {
+		this.parsers = parsers;
+	}
+	
+	public ConsoleOutputStreamSniffer(OutputStream outputStream, IScannerInfoConsoleParser[] parsers) {
+		this(parsers);
+		nOpens = 1;
+		this.outputStream = outputStream;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.io.OutputStream#write(int)
+	 */
+	public void write(int b) throws IOException {
+		currentLine.append((char) b);
+		checkLine(false);
+		if (outputStream != null) {
+			outputStream.write(b);
+		}
+	}
+	/**
+	 * @param flush
+	 */
+	private void checkLine(boolean flush) {
+		String buffer = currentLine.toString();
+		int i = 0;
+		while ((i = buffer.indexOf('\n')) != -1) {
+			String line = buffer.substring(0, i).trim(); // get rid of any trailing \r
+			processLine(line);
+			buffer = buffer.substring(i + 1); // skip the \n and advance
+		}
+		currentLine.setLength(0);
+		if (flush) {
+			if (buffer.length() > 0) {
+				processLine(buffer);
+			}
+		} else {
+			currentLine.append(buffer);
+		}
+	}
+
+	/**
+	 * @param line
+	 */
+	private void processLine(String line) {
+		for (int i = 0; i < parsers.length; ++i) {
+			parsers[i].processLine(line);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see java.io.OutputStream#close()
+	 */
+	public void close() throws IOException {
+		if (nOpens > 0 && --nOpens == 0) {
+			checkLine(true);
+			if (outputStream != null)
+				outputStream.close();
+		}
+		for (int i = 0; i < parsers.length; ++i) {
+			parsers[i].shutdown();
+		}
+	}
+	/* (non-Javadoc)
+	 * @see java.io.OutputStream#flush()
+	 */
+	public void flush() throws IOException {
+		if (outputStream != null) {
+			outputStream.flush();
+		}
+	}
+	/* (non-Javadoc)
+	 * @see java.io.OutputStream#write(byte[], int, int)
+	 */
+	public void write(byte[] b, int off, int len) throws IOException {
+		if (b == null) {
+			throw new NullPointerException();
+		} else if (off != 0 || (len < 0) || (len > b.length)) {
+			throw new IndexOutOfBoundsException();
+		} else if (len == 0) {
+			return;
+		}
+		currentLine.append(new String(b, 0, len));
+		checkLine(false);
+		if (outputStream != null)
+			outputStream.write(b, off, len);
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/DefaultExternalScannerInfoProvider.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/DefaultExternalScannerInfoProvider.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/DefaultExternalScannerInfoProvider.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/DefaultExternalScannerInfoProvider.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,257 @@
+/**********************************************************************
+ * 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.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.CCorePlugin;
+import org.eclipse.cdt.core.CommandLauncher;
+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.IExternalScannerInfoProvider;
+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;
+
+/**
+ * Default external scanner info provider.
+ * Runs an external command (i.e. gcc -c -v) and parses an output for scanner info. 
+ * 
+ * @author vhirsl
+ */
+public class DefaultExternalScannerInfoProvider implements IExternalScannerInfoProvider, IMarkerGenerator {
+	
+	private static final String EXTERNAL_SI_PROVIDER_ERROR = "DefaultExternalScannerInfoProvider.Provider_Error"; //$NON-NLS-1$
+	private static final String EXTERNAL_SI_PROVIDER_CONSOLE_ID = MakeCorePlugin.getUniqueIdentifier() + ".ExternalScannerInfoProviderConsole";	//$NON-NLS-1$
+	
+	private IPath fWorkingDirectory;
+	private IPath fCompileCommand;
+	private String fCompileArguments;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.IExternalScannerInfoProvider#invokeProvider(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.resources.IProject, org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo, java.lang.String[])
+	 */
+	public boolean invokeProvider(IProgressMonitor monitor, IProject currentProject, IScannerConfigBuilderInfo buildInfo, String[] targetSpecificOptions) {
+		if (!initialize(currentProject, buildInfo)) {
+			return false;
+		}
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		monitor.beginTask(MakeCorePlugin.getResourceString("ExternalScannerInfoProvider.Reading_Specs"), 100); //$NON-NLS-1$
+		
+		try {
+			IConsole console = CCorePlugin.getDefault().getConsole(EXTERNAL_SI_PROVIDER_CONSOLE_ID);
+			console.start(currentProject);
+			OutputStream cos = console.getOutputStream();
+
+			// Before launching give visual cues via the monitor
+			monitor.subTask(MakeCorePlugin.getResourceString("ExternalScannerInfoProvider.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("ExternalScannerInfoProvider.Invoking_Command")
+					+ fCompileCommand.toString() + ca); //$NON-NLS-1$
+			cos = new StreamMonitor(new SubProgressMonitor(monitor, 70), cos, 100);
+			
+			OutputStream sniffer = ScannerInfoConsoleParserFactory.getESIProviderOutputSniffer(
+					cos, currentProject, buildInfo);
+			Process p = launcher.execute(fCompileCommand, compileArguments, setEnvironment(launcher), fWorkingDirectory);
+			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(sniffer, sniffer, new SubProgressMonitor(monitor, 0)) != CommandLauncher.OK) {
+					errMsg = launcher.getErrorMessage();
+				}
+				monitor.subTask(MakeCorePlugin.getResourceString("ExternalScannerInfoProvider.Parsing_Output")); //$NON-NLS-1$
+			}
+			else {
+				errMsg = launcher.getErrorMessage();
+			}
+
+			if (errMsg != null) {
+				String errorDesc = MakeCorePlugin.getFormattedString(EXTERNAL_SI_PROVIDER_ERROR, 
+						fCompileCommand.toString() + ca);
+				addMarker(currentProject, -1, errorDesc, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
+			}
+
+			monitor.subTask(MakeCorePlugin.getResourceString("ExternalScannerInfoProvider.Creating_Markers")); //$NON-NLS-1$
+			sniffer.close();
+			cos.close();
+		}
+		catch (Exception e) {
+			CCorePlugin.log(e);
+		}
+		finally {
+			monitor.done();
+		}
+		return true;
+	}
+
+	/**
+	 * @param currentProject
+	 * @param buildInfo
+	 * @return boolean
+	 */
+	private boolean initialize(IProject currentProject, IScannerConfigBuilderInfo buildInfo) {
+		boolean rc = false;
+		if (buildInfo.isDefaultESIProviderCmd()) {
+			fWorkingDirectory = MakeCorePlugin.getWorkingDirectory();
+		}
+		else {
+			fWorkingDirectory = currentProject.getLocation();
+		}
+		fCompileCommand = buildInfo.getESIProviderCommand();
+		if (fCompileCommand != null) {
+			fCompileArguments = buildInfo.getESIProviderArguments();
+			rc = true;
+		}
+		return rc;
+	}
+
+	/**
+	 * @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 + tso.length];
+				for (int i = 0; tokenizer.hasMoreTokens(); ++i) {
+					rv[i] = tokenizer.nextToken();
+				}
+			}
+		}
+		if (rv == null) {
+			rv = new String[tso.length];
+		}
+		for (int i = 0; i < tso.length; ++i) {
+			rv[nTokens + 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", fWorkingDirectory.toOSString()); //$NON-NLS-1$
+		props.put("PWD", fWorkingDirectory.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/IScannerInfoConsoleParserUtility.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/IScannerInfoConsoleParserUtility.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/IScannerInfoConsoleParserUtility.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/IScannerInfoConsoleParserUtility.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,28 @@
+/**********************************************************************
+ * 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 org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Common work required by the scanner info console parsers
+ * 
+ * @author vhirsl
+ */
+public interface IScannerInfoConsoleParserUtility {
+	// Problem marker related
+	public void generateMarker(IResource file, int lineNumber, String desc, int severity, String varName);
+	public boolean reportProblems();
+	// File path management
+	public void changeMakeDirectory(String dir, int dirLevel, boolean enterDir);
+	public IFile findFile(String fileName);
+}
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,337 @@
+/**********************************************************************
+ * 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_ESI_PROVIDER_CMD = PREFIX + ".useDefaultESIProviderCmd"; //$NON-NLS-1$
+	static final String ESI_PROVIDER_COMMAND = PREFIX + ".esiProviderCommand"; //$NON-NLS-1$
+	static final String ESI_PROVIDER_ARGUMENTS = PREFIX + ".esiProviderArguments"; //$NON-NLS-1$
+	static final String ESI_PROVIDER_PARSER_ID = PREFIX + ".esiProviderParserId"; //$NON-NLS-1$
+	static final String MAKE_BUILDER_PARSER_ID = PREFIX + ".makeBuilderParserId"; //$NON-NLS-1$
+	static final String MAKE_BUILDER_PARSER_ENABLED = PREFIX + ".makeBuilderParserEnabled"; //$NON-NLS-1$
+	static final String ESI_PROVIDER_PARSER_ENABLED = PREFIX + ".esiProviderParserEnabled"; //$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#isDefaultESIProviderCmd()
+		 */
+		public boolean isDefaultESIProviderCmd() {
+			if (getString(USE_DEFAULT_ESI_PROVIDER_CMD) == null ||
+				getString(USE_DEFAULT_ESI_PROVIDER_CMD).length() == 0) { // if no property then default to true
+				return true;
+			}
+			return getBoolean(USE_DEFAULT_ESI_PROVIDER_CMD);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setUseDefaultESIProviderCmd(boolean)
+		 */
+		public void setUseDefaultESIProviderCmd(boolean on) throws CoreException {
+			putString(USE_DEFAULT_ESI_PROVIDER_CMD, Boolean.toString(on));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderCommand()
+		 */
+		public IPath getESIProviderCommand() {
+			if (isDefaultESIProviderCmd()) {
+				String command = getESIProviderParameter("defaultCommand"); //$NON-NLS-1$
+				if (command == null) {
+					return new Path("gcc"); //$NON-NLS-1$
+				}
+				return new Path(command);
+			}
+			return new Path(getString(ESI_PROVIDER_COMMAND));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderCommand(org.eclipse.core.runtime.IPath)
+		 */
+		public void setESIProviderCommand(IPath command) throws CoreException {
+			putString(ESI_PROVIDER_COMMAND, command.toString());
+		}
+		
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderArguments()
+		 */
+		public String getESIProviderArguments() {
+			if (isDefaultESIProviderCmd()) {
+				String attributes = getESIProviderParameter("defaultAttributes"); //$NON-NLS-1$
+				if (attributes == null) {
+					attributes = "-c -v"; //$NON-NLS-1$
+				}
+				return attributes;
+			}
+			return getString(ESI_PROVIDER_ARGUMENTS);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderArguments(java.lang.String)
+		 */
+		public void setESIProviderArguments(String args) throws CoreException {
+			putString(ESI_PROVIDER_ARGUMENTS, args);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getESIProviderConsoleParserId()
+		 */
+		public String getESIProviderConsoleParserId() {
+			String parserId = getString(ESI_PROVIDER_PARSER_ID);
+			if (parserId == null || parserId.length() == 0) {
+				String[] parserIds = MakeCorePlugin.getDefault().
+					getScannerInfoConsoleParserIds("externalScannerInfoProvider"); //$NON-NLS-1$
+				// the default is the first one in the registry
+				parserId = parserIds[0];	
+			}
+			return parserId;
+		}
+	
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderConsoleParserId(java.lang.String)
+		 */
+		public void setESIProviderConsoleParserId(String parserId) throws CoreException {
+			putString(ESI_PROVIDER_PARSER_ID, parserId);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#getMakeBuilderConsoleParserId()
+		 */
+		public String getMakeBuilderConsoleParserId() {
+			String parserId = getString(MAKE_BUILDER_PARSER_ID);
+			if (parserId == null || parserId.length() == 0) {
+				String[] parserIds = MakeCorePlugin.getDefault().
+					getScannerInfoConsoleParserIds("makeBuilder"); //$NON-NLS-1$
+				// the default is the first one in the registry
+				parserId = parserIds[0];	
+			}
+			return parserId;
+		}
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setMakeBuilderConsoleParserId(java.lang.String)
+		 */
+		public void setMakeBuilderConsoleParserId(String parserId) throws CoreException {
+			putString(MAKE_BUILDER_PARSER_ID, parserId);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isMakeBuilderConsoleParserEnabled()
+		 */
+		public boolean isMakeBuilderConsoleParserEnabled() {
+			if (getString(MAKE_BUILDER_PARSER_ENABLED) == null ||
+				getString(MAKE_BUILDER_PARSER_ENABLED).length() == 0) { // if no property then default to true
+				return true;
+			}
+			return getBoolean(MAKE_BUILDER_PARSER_ENABLED);
+		}
+		
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setMakeBuilderConsoleParserEnabled(boolean)
+		 */
+		public void setMakeBuilderConsoleParserEnabled(boolean enabled) throws CoreException {
+			putString(MAKE_BUILDER_PARSER_ENABLED, Boolean.toString(enabled));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#isESIProviderConsoleParserEnabled()
+		 */
+		public boolean isESIProviderConsoleParserEnabled() {
+			if (getString(ESI_PROVIDER_PARSER_ENABLED) == null ||
+				getString(ESI_PROVIDER_PARSER_ENABLED).length() == 0) { // if no property then default to true
+				return true;
+			}
+			return getBoolean(ESI_PROVIDER_PARSER_ENABLED);
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo#setESIProviderConsoleParserEnabled(boolean)
+		 */
+		public void setESIProviderConsoleParserEnabled(boolean enabled) throws CoreException {
+			putString(ESI_PROVIDER_PARSER_ENABLED, Boolean.toString(enabled));
+		}
+		
+		protected boolean getBoolean(String property) {
+			return Boolean.valueOf(getString(property)).booleanValue();
+		}
+
+		protected abstract String getBuilderID();
+		protected abstract String getString(String property);
+		protected abstract void putString(String name, String value) throws CoreException;
+
+		protected String getESIProviderParameter(String name) {
+			IExtension extension =
+				Platform.getPluginRegistry().getExtension(
+						MakeCorePlugin.getUniqueIdentifier(),
+						MakeCorePlugin.EXTERNAL_SI_PROVIDER_SIMPLE_ID,
+						// TODO VMIR make this configurable
+						MakeCorePlugin.DEFAULT_EXTERNAL_SI_PROVIDER_ID);
+			if (extension == null)
+				return null;
+			IConfigurationElement[] configs = extension.getConfigurationElements();
+			if (configs.length == 0)
+				return null;
+			IConfigurationElement[] runElement = configs[0].getChildren("run"); //$NON-NLS-1$
+			IConfigurationElement[] paramElement = runElement[0].getChildren("parameter"); //$NON-NLS-1$
+			for (int i = 0; i < paramElement.length; i++) {
+				if (paramElement[i].getAttribute("name").equals(name)) { //$NON-NLS-1$
+					return paramElement[i].getAttribute("value"); //$NON-NLS-1$
+				}
+			}
+			return null;
+		}
+	}
+	
+	private static class Preference extends Store {
+		private Preferences prefs;
+		private String builderID;
+		private boolean useDefaults;
+
+		Preference(Preferences prefs, String builderID, boolean useDefaults) {
+			this.prefs = prefs;
+			this.builderID = builderID;
+			this.useDefaults = useDefaults;
+		}
+
+		protected void putString(String name, String value) {
+			if (useDefaults) {
+				prefs.setDefault(name, value);
+			} else {
+				prefs.setValue(name, value);
+			}
+		}
+
+		protected String getString(String property) {
+			if (useDefaults) {
+				return prefs.getDefaultString(property);
+			}
+			return prefs.getString(property);
+		}
+
+		protected String getBuilderID() {
+			return builderID;
+		}
+	}
+	
+	private static class BuildProperty extends Store {
+		private IProject project;
+		private String builderID;
+		private Map args;
+
+		BuildProperty(IProject project, String builderID) throws CoreException {
+			this.project = project;
+			this.builderID = builderID;
+			ICommand builder = ScannerConfigNature.getBuildSpec(project, 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,343 @@
+/**********************************************************************
+ * 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.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.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.IExternalScannerInfoProvider;
+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 resource
+	 * @param includes
+	 * @param symbols
+	 * @param targetSpecificOptions
+	 */
+	public synchronized void contributeToScannerConfig(IResource resource, List includes, List symbols, List targetSpecificOptions) {
+		IProject project;
+		if (resource == null || (project = resource.getProject()) == null) {
+			// TODO VMIR create a log
+			return;
+		}
+		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();
+		}
+	}
+	
+	/**
+	 * @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);
+		List dSymbols = (List) discoveredSymbols.get(projectName);
+		if (includes == null && dSymbols == null)
+			return false;
+		Set symbols = new HashSet(dSymbols);
+		
+		// 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
+						// TODO VMIR for now add even if it does not exist
+						translatedIncludePaths.add(translatedPath);
+					}
+				}
+				else {
+					// TODO VMIR for now add even if it does not exist
+					translatedIncludePaths.add(translatedPath);
+				}
+			}
+			else {
+				translatedIncludePaths.add(includePath);
+			}
+		}
+		return translatedIncludePaths;
+	}
+
+	/**
+	 * Call ESI provider to get scanner info
+	 *
+	 * @param project
+	 * @param tso
+	 * @param monitor
+	 */
+	private void getProviderScannerInfo(final IProject project, 
+										final List tso, 
+										final IProgressMonitor monitor) {
+		// 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);
+		}
+		if (info.isESIProviderConsoleParserEnabled()) {
+			final IScannerConfigBuilderInfo buildInfo = info;
+			final IExternalScannerInfoProvider esiProvider = MakeCorePlugin.getDefault().
+				getExternalScannerInfoProvider(MakeCorePlugin.DEFAULT_EXTERNAL_SI_PROVIDER_ID);
+			if (esiProvider != null) {
+				ISafeRunnable runnable = new ISafeRunnable() {
+					public void run() {
+						String[] tsoArray;
+						if (tso == null) {
+							tsoArray = new String[0];
+						}
+						else {
+							tsoArray = (String[])tso.toArray(new String[tso.size()]);
+						}
+						esiProvider.invokeProvider(monitor, project, buildInfo, tsoArray);
+					}
+		
+					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$
+		getProviderScannerInfo(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/ScannerInfoConsoleParserFactory.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/ScannerInfoConsoleParserFactory.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,95 @@
+/**********************************************************************
+ * 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.io.OutputStream;
+
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerConfigBuilderInfo;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser;
+import org.eclipse.cdt.make.core.scannerconfig.ScannerConfigBuilder;
+import org.eclipse.cdt.make.internal.core.scannerconfig.util.ScannerInfoConsoleParserUtility;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A factory that creates a ConsoleOutputStreamSniffer,
+ * ScannerInfoConsoleParser and optionally a ScannerInfoConsoleParserUtility.
+ * 
+ * @author vhirsl
+ */
+public class ScannerInfoConsoleParserFactory {
+
+	/**
+	 * Creates a ConsoleOutputStreamSniffer, make builder scanner info console parser
+	 * and a utility.
+	 * 
+	 * @param outputStream
+	 * @param currentProject
+	 * @param markerGenerator
+	 * @param scBuildInfo
+	 * @return OutputStream
+	 */
+	public static OutputStream getESIProviderOutputSniffer(OutputStream outputStream,
+														   IProject currentProject,
+														   IScannerConfigBuilderInfo scBuildInfo) {
+		if (scBuildInfo.isESIProviderConsoleParserEnabled()) {
+			// get the ESIProvider console parser 
+			IScannerInfoConsoleParser clParser = MakeCorePlugin.getDefault().
+				getScannerInfoConsoleParser(scBuildInfo.getESIProviderConsoleParserId());
+			// initialize it with the utility
+			clParser.startup(currentProject, null /*new ScannerInfoConsoleParserUtility(
+				currentProject, null, markerGenerator)*/);
+			// create an output stream sniffer
+			return new ConsoleOutputStreamSniffer(outputStream, new 
+				IScannerInfoConsoleParser[] {clParser});
+		}
+		return outputStream;
+	}
+	
+	/**
+	 * Creates a ConsoleOutputStreamSniffer, ESI provider scanner info console parser
+	 * and a utility.
+	 * 
+	 * @param outputStream
+	 * @param currentProject
+	 * @param workingDirectory
+	 * @param markerGenerator
+	 * @return OutputStream
+	 */
+	public static OutputStream getMakeBuilderOutputSniffer(OutputStream outputStream,
+														   IProject currentProject,
+														   IPath workingDirectory,
+														   IMarkerGenerator markerGenerator) {
+		try {
+			// get the SC builder settings
+			IScannerConfigBuilderInfo scBuildInfo = MakeCorePlugin.
+				createScannerConfigBuildInfo(currentProject, ScannerConfigBuilder.BUILDER_ID);
+			if (scBuildInfo.isMakeBuilderConsoleParserEnabled()) {
+				// get the make builder console parser 
+				IScannerInfoConsoleParser clParser = MakeCorePlugin.getDefault().
+					getScannerInfoConsoleParser(scBuildInfo.getMakeBuilderConsoleParserId());			
+				// initialize it with the utility
+				clParser.startup(currentProject, new ScannerInfoConsoleParserUtility(
+					currentProject, workingDirectory, markerGenerator));
+				// create an output stream sniffer
+				return new ConsoleOutputStreamSniffer(outputStream, new 
+					IScannerInfoConsoleParser[] {clParser});
+			}
+		} 
+		catch (CoreException e) {
+			MakeCorePlugin.log(e.getStatus());
+		}
+		return outputStream;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerConfigUtil.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,57 @@
+/**********************************************************************
+ * 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.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * GCC related utility class
+ * 
+ * @author vhirsl
+ */
+public class GCCScannerConfigUtil {
+	public static final String CPP_SPECS_FILE = "specs.cpp"; //$NON-NLS-1$ 
+	public static final String C_SPECS_FILE = "specs.c";  //$NON-NLS-1$
+
+	public static void createSpecs() {
+		IPath path = MakeCorePlugin.getWorkingDirectory();
+		try {
+			createSpecsFile(path, CPP_SPECS_FILE);
+			createSpecsFile(path, C_SPECS_FILE);
+		} catch (CoreException e) {
+			MakeCorePlugin.log(e);
+		}
+	}
+
+	private static void createSpecsFile(IPath path, String fileName) throws CoreException {
+		IPath specs = path.append(fileName);
+		File specsFile = specs.toFile();
+		if (!specsFile.exists()) {
+			try {
+				FileOutputStream file = new FileOutputStream(specsFile);
+				file.write('\n');
+				file.close();
+			} catch (IOException e) {
+				throw new CoreException(new Status(IStatus.ERROR,
+						MakeCorePlugin.getDefault().getDescriptor().getUniqueIdentifier(), -1,
+						MakeCorePlugin.getResourceString("GCCScannerConfigUtil.Error_Message"), e));	//$NON-NLS-1$
+			}
+		}
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCScannerInfoConsoleParser.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,197 @@
+/**********************************************************************
+ * 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.CCProjectNature;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser;
+import org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility;
+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 GCCScannerInfoConsoleParser implements IScannerInfoConsoleParser {
+
+	private IProject fProject = null;
+	private IScannerInfoConsoleParserUtility fUtil = null;
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#startup(org.eclipse.core.resources.IProject)
+	 */
+	public void startup(IProject project, IScannerInfoConsoleParserUtility util) {
+		fProject = project;
+		fUtil = util;
+		
+		IPath workingDirectory = MakeCorePlugin.getWorkingDirectory();
+		String targetFile = "dummy";	//$NON-NLS-1$
+		try {
+			if (project.hasNature(CCProjectNature.CC_NATURE_ID)) {
+				targetFile = GCCScannerConfigUtil.CPP_SPECS_FILE;
+			}
+			else if (project.hasNature(CProjectNature.C_NATURE_ID)) {
+				targetFile = GCCScannerConfigUtil.C_SPECS_FILE;
+			}
+		} catch (CoreException e) {
+			//TODO VMIR better error handling
+			MakeCorePlugin.log(e.getStatus());
+		}
+		IPath path2File = workingDirectory.append(targetFile);
+		if (!path2File.toFile().exists()) {
+			GCCScannerConfigUtil.createSpecs();
+		}
+		List targetSpecificOptions = new ArrayList();
+		targetSpecificOptions.add(targetFile);
+		
+		ScannerInfoCollector.getInstance().
+			contributeToScannerConfig(project, null, null, targetSpecificOptions);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.ScannerInfoConsoleParserUtility#processLine(java.lang.String)
+	 */
+	public boolean processLine(String line) {
+		boolean rc = false;
+		// make\[[0-9]*\]:  error_desc
+		int firstColon= line.indexOf(':');
+		if (firstColon != -1 && line.startsWith("make")) { //$NON-NLS-1$
+			boolean enter = false;
+			String msg = line.substring(firstColon + 1).trim();		
+			if ((enter = msg.startsWith("Entering directory")) || //$NON-NLS-1$
+			    (msg.startsWith("Leaving directory"))) { //$NON-NLS-1$
+			    int s = msg.indexOf('`');
+			    int e = msg.indexOf('\'');
+			    if (s != -1 && e != -1) {
+			    	String dir = msg.substring(s+1, e);
+			    	fUtil.changeMakeDirectory(dir, getDirectoryLevel(line), enter);
+			    	return rc;
+				}
+			}
+		}
+		// 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$
+						 token.equals("-posix") ||		//$NON-NLS-1$
+						 token.equals("-pthread")) {	//$NON-NLS-1$
+					if (!targetSpecificOptions.contains(token))
+						targetSpecificOptions.add(token);
+				}
+				else {
+					String possibleFileName = token.toLowerCase();
+					if (possibleFileName.startsWith("../") ||	//$NON-NLS-1$
+						possibleFileName.startsWith("./") ||	//$NON-NLS-1$
+						possibleFileName.startsWith("/") ||		//$NON-NLS-1$
+						possibleFileName.startsWith("$(") ||	//$NON-NLS-1$
+						possibleFileName.endsWith(".c") || 		//$NON-NLS-1$
+						possibleFileName.endsWith(".cpp") ||	//$NON-NLS-1$
+						possibleFileName.endsWith(".cc") ||		//$NON-NLS-1$
+						possibleFileName.endsWith(".cxx")) {	//$NON-NLS-1$
+						
+						fileName = token;
+					}
+				}
+			}
+			
+			IFile file = null;
+			IProject project = fProject;   
+			if (fileName != null) {
+				file = fUtil.findFile(fileName);
+				if (file != null) {
+					project = file.getProject();
+//					fUtil.translateRelativePaths(file, fileName, includes);
+				}
+			}
+			// Contribute discovered includes and symbols to the ScannerInfoCollector
+			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();
+				fUtil.generateMarker(file, -1, "Found an include path: "+iPath, severity, iPath);
+			}
+			for (Iterator i = symbols.iterator(); i.hasNext(); ) {
+				String symbol = (String)i.next();
+				fUtil.generateMarker(file, -1, "Found a symbol definition: "+symbol, severity, symbol);
+			}
+			
+		}
+		return rc;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#shutdown()
+	 */
+	public void shutdown() {
+		if (fUtil != null) {
+			fUtil.reportProblems();
+		}
+	}
+
+	private int getDirectoryLevel(String line) {
+		int s = line.indexOf('[');
+		int num = 0;
+		if (s != -1) {
+			int e = line.indexOf(']');
+			String number = line.substring(s + 1, e).trim();		
+			try {
+				num = Integer.parseInt(number);
+			} catch (NumberFormatException exc) {
+			}
+		}
+		return num;
+	}
+}
Index: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/gnu/GCCSpecsConsoleParser.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,109 @@
+/**********************************************************************
+ * 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.make.core.scannerconfig.IScannerInfoConsoleParser;
+import org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility;
+import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoCollector;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Parses output of gcc -c -v specs.c or
+ *                  g++ -c -v specs.cpp
+ * command
+ * 
+ * @author vhirsl
+ */
+public class GCCSpecsConsoleParser implements IScannerInfoConsoleParser {
+	private final int STATE_BEGIN = 0;
+	private final int STATE_SPECS_STARTED = 1;
+	private final int STATE_INCLUDES_STARTED = 2;
+
+	private IProject project = null;
+	private IScannerInfoConsoleParserUtility util = null;
+	
+	private int state = STATE_BEGIN;
+	private List symbols = new ArrayList();
+	private List includes = new ArrayList();
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoConsoleParser#initialize(org.eclipse.core.resources.IProject, org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility)
+	 */
+	public void startup(IProject project, IScannerInfoConsoleParserUtility util) {
+		this.project = project;
+		this.util = util;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#processLine(java.lang.String)
+	 */
+	public boolean processLine(String line) {
+		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(project, includes, symbols, null);
+			
+		return rc;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParser#shutdown()
+	 */
+	public void shutdown() {
+		if (util != null) {
+			util.reportProblems();
+		}
+	}
+}
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;
+
+/**
+ * Executes external command 'cygpath' to translate cygpaths to absolute paths.
+ * 
+ * @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$
+			project.getLocation());				//$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,95 @@
+/**********************************************************************
+ * 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/ScannerInfoConsoleParserUtility.java
===================================================================
RCS file: src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerInfoConsoleParserUtility.java
diff -N src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerInfoConsoleParserUtility.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/make/internal/core/scannerconfig/util/ScannerInfoConsoleParserUtility.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,302 @@
+/**********************************************************************
+ * 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.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
+import org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * Implements error reporting mechanism and file/path translation mechanism
+ * Taken from ErrorParserManager and modified.
+ * 
+ * @author vhirsl
+ */
+public class ScannerInfoConsoleParserUtility implements IScannerInfoConsoleParserUtility {
+	private IProject fProject;
+	private IPath fBaseDirectory;
+	private IMarkerGenerator fMarkerGenerator;
+	private ArrayList fErrors;
+
+	/*
+	 * For tracking the location of files being compiled
+	 */
+	private Map fFilesInProject;
+	private List fCollectedFiles;
+	private List fNameConflicts;
+	private Vector fDirectoryStack;
+	
+	public ScannerInfoConsoleParserUtility(IProject project, IPath workingDirectory, IMarkerGenerator markerGenerator) {
+		fProject = project;
+		fMarkerGenerator = markerGenerator;
+		fBaseDirectory = fProject.getLocation();
+		fErrors = new ArrayList();
+
+		fFilesInProject = new HashMap();
+		fCollectedFiles = new ArrayList();
+		fNameConflicts = new ArrayList();
+		fDirectoryStack = new Vector();
+
+		collectFiles(fProject, fCollectedFiles);
+
+		for (int i = 0; i < fCollectedFiles.size(); i++) {
+			IFile curr = (IFile) fCollectedFiles.get(i);
+			Object existing = fFilesInProject.put(curr.getName(), curr);
+			if (existing != null) {
+				fNameConflicts.add(curr.getName());
+			}
+		}
+		if (workingDirectory != null) {
+			pushDirectory(workingDirectory);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility#reportProblems()
+	 */
+	public boolean reportProblems() {
+		boolean reset = false;
+		for (Iterator iter = fErrors.iterator(); iter.hasNext(); ) {
+			Problem problem = (Problem) iter.next();
+			if (problem.severity == IMarkerGenerator.SEVERITY_ERROR_BUILD) {
+				reset = true;
+			}
+			if (problem.file == null) {
+				fMarkerGenerator.addMarker(
+					fProject,
+					problem.lineNumber,
+					problem.description,
+					problem.severity,
+					problem.variableName);
+			} else {
+				fMarkerGenerator.addMarker(
+					problem.file,
+					problem.lineNumber,
+					problem.description,
+					problem.severity,
+					problem.variableName);
+			}
+		}
+		fErrors.clear();
+		return reset;
+	}
+
+	protected class Problem {
+		protected IResource file;
+		protected int lineNumber;
+		protected String description;
+		protected int severity;
+		protected String variableName;
+
+		public Problem(IResource file, int lineNumber, String desciption, int severity, String variableName) {
+			this.file = file;
+			this.lineNumber = lineNumber;
+			this.description = desciption;
+			this.severity = severity;
+			this.variableName = variableName;
+		}
+	}
+
+	/**
+	 * Called by the console line parsers to generate a problem marker.
+	 */
+	public void generateMarker(IResource file, int lineNumber, String desc, int severity, String varName) {
+		Problem problem = new Problem(file, lineNumber, desc, severity, varName);
+		fErrors.add(problem);
+	}
+
+	/**
+	 * Called by the console line parsers to find a file with a given name.
+	 * @param fileName
+	 * @return IFile or null
+	 */
+	public IFile findFile(String fileName) {
+		IFile file = findFilePath(fileName);
+		if (file == null) {
+			// Try the project's map.
+			file = findFileName(fileName);
+			if (file != null) {
+				// If there is a conflict then try all files in the project.
+				if (isConflictingName(fileName)) {
+					file = null;
+					// Create a problem marker
+					generateMarker(fProject, -1, "Ambiguous file path: "+fileName, IMarkerGenerator.SEVERITY_ERROR_RESOURCE, null);				
+				}
+			}
+		}
+		return file;
+	}
+	
+	/**
+	 * @param filePath
+	 * @return
+	 */
+	protected IFile findFilePath(String filePath) {
+		IPath path = null;
+		IPath fp = new Path(filePath);
+		if (fp.isAbsolute()) {
+			if (fBaseDirectory.isPrefixOf(fp)) {
+				int segments = fBaseDirectory.matchingFirstSegments(fp);
+				path = fp.removeFirstSegments(segments);
+			} else {
+				path = fp;
+			}
+		} else {
+			path = (IPath) getWorkingDirectory().append(filePath);
+		}
+
+		IFile file = null;
+		// The workspace may throw an IllegalArgumentException
+		// Catch it and the parser should fallback to scan the entire project.
+		try {
+			file = findFileInWorkspace(path);
+		} catch (Exception e) {
+		}
+
+		// We have to do another try, on Windows for cases like "TEST.C" vs "test.c"
+		// We use the java.io.File canonical path.
+		if (file == null || !file.exists()) {
+			File f = path.toFile();
+			try {
+				String canon = f.getCanonicalPath();
+				path = new Path(canon);
+				file = findFileInWorkspace(path);
+			} catch (IOException e1) {
+			}
+		}
+		return (file != null && file.exists()) ? file : null;
+	}
+
+	/**
+	 * @param fileName
+	 * @return
+	 */
+	protected IFile findFileName(String fileName) {
+		IPath path = new Path(fileName);
+		return (IFile) fFilesInProject.get(path.lastSegment());
+	}
+
+	protected IFile findFileInWorkspace(IPath path) {
+		IFile file = null;
+		if (path.isAbsolute()) {
+			IWorkspaceRoot root = fProject.getWorkspace().getRoot();
+			file =  root.getFileForLocation(path);
+			// It may be a link resource so we must check it also.
+			if (file == null) {
+				IFile[] files = root.findFilesForLocation(path);
+				for (int i = 0; i < files.length; i++) {
+					if (files[i].getProject().equals(fProject)) {
+						file = files[i];
+						break;
+					}
+				}
+			}
+
+		} else {
+			file = fProject.getFile(path);
+		}
+		return file;
+	}
+
+	protected void collectFiles(IContainer parent, List result) {
+		try {
+			IResource[] resources = parent.members();
+			for (int i = 0; i < resources.length; i++) {
+				IResource resource = resources[i];
+				if (resource instanceof IFile) {
+					result.add(resource);
+				} else if (resource instanceof IContainer) {
+					collectFiles((IContainer) resource, result);
+				}
+			}
+		} catch (CoreException e) {
+			MakeCorePlugin.log(e.getStatus());
+		}
+	}
+
+	protected boolean isConflictingName(String fileName) {
+		IPath path = new Path(fileName);
+		return fNameConflicts.contains(path.lastSegment());
+	}
+
+	protected IPath getWorkingDirectory() {
+		if (fDirectoryStack.size() != 0) {
+			return (IPath) fDirectoryStack.lastElement();
+		}
+		// Fallback to the Project Location
+		// FIXME: if the build did not start in the Project ?
+		return fBaseDirectory;
+	}
+
+	protected void pushDirectory(IPath dir) {
+		if (dir != null) {
+			IPath pwd = null;
+			if (fBaseDirectory.isPrefixOf(dir)) {
+				int segments = fBaseDirectory.matchingFirstSegments(dir);
+				pwd = dir.removeFirstSegments(segments);
+			} else {
+				pwd = dir;
+			}
+			fDirectoryStack.addElement(pwd);
+		}
+	}
+
+	protected IPath popDirectory() {
+		int i = getDirectoryLevel();
+		if (i != 0) {
+			IPath dir = (IPath) fDirectoryStack.lastElement();
+			fDirectoryStack.removeElementAt(i - 1);
+			return dir;
+		}
+		return new Path("");	//$NON-NLS-1$
+	}
+
+	protected int getDirectoryLevel() {
+		return fDirectoryStack.size();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.make.internal.core.scannerconfig.IScannerInfoConsoleParserUtility#changeMakeDirectory(java.lang.String, int, boolean)
+	 */
+	public void changeMakeDirectory(String dir, int dirLevel, boolean enterDir) {
+    	if (enterDir) {
+    		/* Sometimes make screws up the output, so
+    		 * "leave" events can't be seen.  Double-check level
+    		 * here.
+    		 */
+			for (int parseLevel = getDirectoryLevel(); dirLevel < parseLevel; parseLevel = getDirectoryLevel()) {
+				popDirectory();
+			}
+    		pushDirectory(new Path(dir));
+    	} else {
+    		popDirectory();
+    		/* Could check to see if they match */
+    	}
+	}
+
+}
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.8
diff -u -r1.8 plugin.properties
--- plugin.properties	2 Mar 2004 21:37:42 -0000	1.8
+++ plugin.properties	4 Mar 2004 21:39:15 -0000
@@ -43,3 +43,5 @@
  
 MakefileEditor.name=Makefile Editor
 
+PropertyScannerConfig.name=Scanner Configuration Discovery
+PreferenceScannerConfig.name=Scanner Configuration Discovery
Index: plugin.xml
===================================================================
retrieving revision 1.27
diff -u -r1.27 plugin.xml
--- plugin.xml	2 Mar 2004 21:37:42 -0000	1.27
+++ plugin.xml	4 Mar 2004 21:39:15 -0000
@@ -26,7 +26,6 @@
       <import plugin="org.eclipse.core.runtime.compatibility"/>
    </requires>
 
-
    <extension
          point="org.eclipse.ui.newWizards">
       <wizard
@@ -392,6 +391,29 @@
                id="org.eclipse.cdt.make.ui.makeTargetActionSet">
          </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.12
diff -u -r1.12 MakeResources.properties
--- src/org/eclipse/cdt/make/internal/ui/MakeResources.properties	2 Mar 2004 21:37:42 -0000	1.12
+++ src/org/eclipse/cdt/make/internal/ui/MakeResources.properties	4 Mar 2004 21:39:16 -0000
@@ -183,3 +183,19 @@
 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.siBuilder.parser.group_label=Build output parser options
+ScannerConfigPage.siBuilder.parser.enable.label=Enable build output parser
+ScannerConfigPage.siBuilder.parser.label=Make build output parser:
+ScannerConfigPage.siProvider.cmd.group_label=Generate scanner info command
+ScannerConfigPage.siProvider.cmd.use_default=Use default
+ScannerConfigPage.siProvider.cmd.label=Generate scanner info command:
+ScannerConfigPage.siProvider.parser.group_label=Command output parser options
+ScannerConfigPage.siProvider.parser.enable.label=Enable command output parser
+ScannerConfigPage.siProvider.parser.label=Command output parser:
+
+ScannerConfigPage.siProvider.cmd.error_message=Must enter a 'generate scanner info' command
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	4 Mar 2004 21:39:18 -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,100 @@
+/**********************************************************************
+ * 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;
+
+/**
+ * Scanner config preference page
+ * @author vhirsl
+ */
+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() {
+		setValid(fScannerConfigPage.isValid());
+		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();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.IPreferencePage#isValid()
+	 */
+	public boolean isValid() {
+		updateContainer();
+		return super.isValid();
+	}
+}
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,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.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;
+
+/**
+ * Scanner config property page
+ * @author vhirsl
+ */
+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() {
+		setValid(fScannerConfigPage.isValid());
+		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();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.IPreferencePage#isValid()
+	 */
+	public boolean isValid() {
+		updateContainer();
+		return super.isValid();
+	}
+}
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,458 @@
+/**********************************************************************
+ * 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 java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+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.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+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.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+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;
+
+/**
+ * Scanner Config settings page
+ * 
+ * @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 SI_BUILD_PARSER_GROUP = PREFIX + ".siBuilder.parser.group_label"; //$NON-NLS-1$ 
+	private static final String SI_BUILD_PARSER_LABEL = PREFIX + ".siBuilder.parser.label"; //$NON-NLS-1$
+	private static final String ENABLE_SI_BUILD_PARSER = PREFIX + ".siBuilder.parser.enable.label"; //$NON-NLS-1$
+	private static final String SI_PROVIDER_CMD_GROUP = PREFIX + ".siProvider.cmd.group_label"; //$NON-NLS-1$
+	private static final String SI_PROVIDER_CMD_USE_DEFAULT = PREFIX + ".siProvider.cmd.use_default"; //$NON-NLS-1$
+	private static final String SI_PROVIDER_CMD_LABEL = PREFIX + ".siProvider.cmd.label"; //$NON-NLS-1$
+	private static final String SI_PROVIDER_PARSER_GROUP = PREFIX + ".siProvider.parser.group_label"; //$NON-NLS-1$
+	private static final String ENABLE_SI_PROVIDER_PARSER = PREFIX + ".siProvider.parser.enable.label";	//$NON-NLS-1$
+	private static final String SI_PROVIDER_PARSER_LABEL = PREFIX + ".siProvider.parser.label"; //$NON-NLS-1$
+	private static final String SI_PROVIDER_CMD_ERROR_MESSAGE = PREFIX + ".siProvider.cmd.error_message"; //$NON-NLS-1$
+	
+	private boolean addTitle = false;
+
+	private Button autoDiscovery;
+
+	private Button defButton;
+	private Text esiProviderCommand;
+	
+	private Button enableBuilderParserButton;
+	private Combo makeBuilderSIParserComboBox;
+	private Button enableProviderParserButton;
+	private Combo esiProviderParserComboBox;
+	
+	private IScannerConfigBuilderInfo fBuildInfo;
+	private Map builderParsers = new HashMap();
+	private String initialBuilderParserId = null;
+	private Map providerParsers = new HashMap();
+	private String initialProviderParserId = null;
+	
+	/**
+	 * 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#isValid()
+	 */
+	public boolean isValid() {
+		if (!useDefaultSpecsCmd()) {
+			String cmd = getSIProviderCommandLine();
+			if (cmd == null || cmd.length() == 0) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/* (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);
+		}
+		retrieveSIConsoleParsers();
+		initialBuilderParserId = fBuildInfo.getMakeBuilderConsoleParserId();	//$NON-NLS-1$
+		initialProviderParserId = fBuildInfo.getESIProviderConsoleParserId();	//$NON-NLS-1$
+	}
+	
+	/**
+	 * Fills console parser maps
+	 */
+	private void retrieveSIConsoleParsers() {
+		IExtensionPoint ep = MakeCorePlugin.getDefault().getDescriptor().
+			getExtensionPoint(MakeCorePlugin.SI_CONSOLE_PARSER_SIMPLE_ID);
+		if (ep != null) {
+			IExtension[] extensions = ep.getExtensions();
+			for (int i = 0; i < extensions.length; ++i) {
+				String parserId = extensions[i].getUniqueIdentifier();
+				String label = extensions[i].getLabel();
+				IConfigurationElement[] elements = (IConfigurationElement[]) extensions[i].getConfigurationElements();
+				String commandId = elements[0].getAttribute("commandId");	//$NON-NLS-1$
+				if (commandId.equals("makeBuilder") || commandId.equals("all")) {	//$NON-NLS-1$//$NON-NLS-2$
+					builderParsers.put(label, parserId);
+				}
+				if (commandId.equals("externalScannerInfoProvider") || commandId.equals("all")) {	//$NON-NLS-1$//$NON-NLS-2$
+					providerParsers.put(label, parserId);
+				}
+			}
+		}
+	}
+
+	/* (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.setUseDefaultESIProviderCmd(useDefaultSpecsCmd());
+		if (!useDefaultSpecsCmd()) {
+			String esiProviderLine = getSIProviderCommandLine();
+			int start = 0;
+			int end = -1;
+			if (esiProviderLine.startsWith("\"")) { //$NON-NLS-1$
+				start = 1;
+				end = esiProviderLine.indexOf('"', 1);
+			}
+			else {
+				end = esiProviderLine.indexOf(' ');
+			}
+			IPath path;
+			if (end == -1) {
+				path = new Path(esiProviderLine);
+			} else {
+				path = new Path(esiProviderLine.substring(start, end));
+			}
+			buildInfo.setESIProviderCommand(path);
+			String args = ""; //$NON-NLS-1$
+			if (end != -1) {
+				args = esiProviderLine.substring(end + 1);
+			}
+			buildInfo.setESIProviderArguments(args);
+		}
+		buildInfo.setMakeBuilderConsoleParserEnabled(enableBuilderParser());
+		if (enableBuilderParser()) {
+			buildInfo.setMakeBuilderConsoleParserId(
+					(String)builderParsers.get(makeBuilderSIParserComboBox.getText()));
+		}
+		buildInfo.setESIProviderConsoleParserEnabled(enableProviderParser());
+		if (enableProviderParser()) {
+			buildInfo.setESIProviderConsoleParserId(
+					(String)providerParsers.get(esiProviderParserComboBox.getText()));
+		}
+	}
+
+	/* (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.getESIProviderCommand();
+		if (sCommand != null) {
+			StringBuffer cmd = new StringBuffer(sCommand.toOSString());
+			String args = buildInfo.getESIProviderArguments();
+			if (args != null && !args.equals("")) { //$NON-NLS-1$
+				cmd.append(' ');
+				cmd.append(args);
+			}
+			esiProviderCommand.setText(cmd.toString());
+		}
+		if (buildInfo.isDefaultESIProviderCmd()) {
+			esiProviderCommand.setEnabled(false);
+		} else {
+			esiProviderCommand.setEnabled(true);
+		}
+		defButton.setSelection(buildInfo.isDefaultESIProviderCmd());
+		
+		String builderParserId = buildInfo.getMakeBuilderConsoleParserId();
+		for (Iterator i = builderParsers.keySet().iterator(); i.hasNext(); ) {
+			String builderParser = (String) i.next();
+			if (builderParserId.equals((String) builderParsers.get(builderParser))) {
+				makeBuilderSIParserComboBox.setText(builderParser);
+			}
+		}
+		enableBuilderParserButton.setSelection(buildInfo.isMakeBuilderConsoleParserEnabled());
+		makeBuilderSIParserComboBox.setEnabled(enableBuilderParser());
+
+		String providerParserId = buildInfo.getMakeBuilderConsoleParserId();
+		for (Iterator i = providerParsers.keySet().iterator(); i.hasNext(); ) {
+			String providerParser = (String) i.next();
+			if (providerParserId.equals((String) builderParsers.get(providerParser))) {
+				esiProviderParserComboBox.setText(providerParser);
+			}
+		}
+		enableProviderParserButton.setSelection(buildInfo.isESIProviderConsoleParserEnabled());
+		esiProviderParserComboBox.setEnabled(enableProviderParser());
+	}
+
+	/* (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);
+		createBuildOutputParserControls(composite);
+		createAfterBuildCmdControls(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 createBuildOutputParserControls(Composite parent) {
+//		ControlFactory.insertSpace(parent, 1, 10);
+		Group bopGroup = ControlFactory.createGroup(parent, 
+			MakeUIPlugin.getResourceString(SI_BUILD_PARSER_GROUP), 2);
+		((GridLayout)bopGroup.getLayout()).marginHeight = 5;
+		((GridLayout)bopGroup.getLayout()).marginWidth = 5;
+		((GridData)bopGroup.getLayoutData()).verticalAlignment = GridData.FILL;
+
+		enableBuilderParserButton = ControlFactory.createCheckBox(bopGroup, 
+			MakeUIPlugin.getResourceString(ENABLE_SI_BUILD_PARSER));
+		((GridData)enableBuilderParserButton.getLayoutData()).horizontalSpan = 2;
+		boolean enabledBuilderParser = fBuildInfo.isMakeBuilderConsoleParserEnabled();
+		enableBuilderParserButton.setSelection(enabledBuilderParser);
+		enableBuilderParserButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				makeBuilderSIParserComboBox.setEnabled(enableBuilderParser());
+				getContainer().updateContainer();
+			}
+		});
+			
+		Label label = ControlFactory.createLabel(bopGroup, 
+				MakeUIPlugin.getResourceString(SI_BUILD_PARSER_LABEL));
+		((GridData)label.getLayoutData()).grabExcessHorizontalSpace = false;
+		
+		makeBuilderSIParserComboBox = new Combo(bopGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
+
+		// fill the combobox and set the initial value
+		Iterator items = builderParsers.keySet().iterator();
+		while (items.hasNext()) {
+			String parser = (String) items.next();
+			makeBuilderSIParserComboBox.add(parser);
+			if (initialBuilderParserId.equals(builderParsers.get(parser))) {
+				makeBuilderSIParserComboBox.setText(parser);
+			}
+		}
+		makeBuilderSIParserComboBox.setEnabled(enabledBuilderParser);
+	}
+	
+	private void createAfterBuildCmdControls(Composite parent) {
+		createESIProviderCmdControls(parent);
+				
+		Group abcParserGroup = ControlFactory.createGroup(parent, 
+				MakeUIPlugin.getResourceString(SI_PROVIDER_PARSER_GROUP), 2);
+		((GridData)abcParserGroup.getLayoutData()).horizontalSpan = 2;
+
+		enableProviderParserButton = ControlFactory.createCheckBox(abcParserGroup, 
+				MakeUIPlugin.getResourceString(ENABLE_SI_PROVIDER_PARSER));
+		((GridData)enableProviderParserButton.getLayoutData()).horizontalSpan = 2;
+		boolean enabledProviderParser = fBuildInfo.isESIProviderConsoleParserEnabled();
+		enableProviderParserButton.setSelection(enabledProviderParser);
+		enableProviderParserButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				esiProviderParserComboBox.setEnabled(enableProviderParser());
+				getContainer().updateContainer();
+			}
+		});
+
+		Label label = ControlFactory.createLabel(abcParserGroup, 
+				MakeUIPlugin.getResourceString(SI_PROVIDER_PARSER_LABEL));
+		((GridData)label.getLayoutData()).grabExcessHorizontalSpace = false;
+		
+		esiProviderParserComboBox = new Combo(abcParserGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
+
+		// fill the combobox and set the initial value
+		Iterator items = providerParsers.keySet().iterator();
+		while (items.hasNext()) {
+			String parser = (String) items.next();
+			esiProviderParserComboBox.add(parser);
+			if (initialProviderParserId.equals(providerParsers.get(parser))) {
+				esiProviderParserComboBox.setText(parser);
+			}
+		}
+		esiProviderParserComboBox.setEnabled(enabledProviderParser);
+	}
+	
+	private void createESIProviderCmdControls(Composite parent) {
+		Group group = ControlFactory.createGroup(parent, 
+				MakeUIPlugin.getResourceString(SI_PROVIDER_CMD_GROUP), 2);
+		((GridData)group.getLayoutData()).horizontalSpan = 2;
+		defButton = ControlFactory.createCheckBox(group, 
+				MakeUIPlugin.getResourceString(SI_PROVIDER_CMD_USE_DEFAULT));
+		defButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				esiProviderCommand.setEnabled(!useDefaultSpecsCmd());
+				getContainer().updateContainer();
+			}
+		});
+		((GridData) (defButton.getLayoutData())).horizontalAlignment = GridData.FILL_HORIZONTAL;
+		((GridData) (defButton.getLayoutData())).horizontalSpan = 2;
+		Label label = ControlFactory.createLabel(group, 
+				MakeUIPlugin.getResourceString(SI_PROVIDER_CMD_LABEL));
+		((GridData) (label.getLayoutData())).horizontalAlignment = GridData.BEGINNING;
+		((GridData) (label.getLayoutData())).grabExcessHorizontalSpace = false;
+		esiProviderCommand = ControlFactory.createTextField(group, SWT.SINGLE | SWT.BORDER);
+		((GridData) (esiProviderCommand.getLayoutData())).horizontalAlignment = GridData.FILL;
+		((GridData) (esiProviderCommand.getLayoutData())).grabExcessHorizontalSpace = true;
+		esiProviderCommand.addListener(SWT.Modify, new Listener() {
+			public void handleEvent(Event e) {
+				getContainer().updateContainer();
+			}
+		});
+		IPath sCommand = fBuildInfo.getESIProviderCommand();
+		if (sCommand != null) {
+			StringBuffer cmd = new StringBuffer(sCommand.toOSString());
+			String args = fBuildInfo.getESIProviderArguments();
+			if (args != null && args.length() > 0) { 
+				cmd.append(' ');
+				cmd.append(args);
+			}
+			esiProviderCommand.setText(cmd.toString());
+		}
+		if (fBuildInfo.isDefaultESIProviderCmd()) {
+			esiProviderCommand.setEnabled(false);
+		}
+		defButton.setSelection(fBuildInfo.isDefaultESIProviderCmd());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#getErrorMessage()
+	 */
+	public String getErrorMessage() {
+		if (!useDefaultSpecsCmd()) {
+			String cmd = getSIProviderCommandLine();
+			if (cmd == null || cmd.length() == 0) {
+				return MakeUIPlugin.getResourceString(SI_PROVIDER_CMD_ERROR_MESSAGE);
+//				return "Must enter a 'generate scanner info' command";	//$NON-NLS-1$
+			}
+		}
+		return super.getErrorMessage();
+	}
+
+	private boolean useDefaultSpecsCmd() {
+		return defButton.getSelection();
+	}
+
+	private String getSIProviderCommandLine() {
+		return esiProviderCommand.getText().trim();
+	}
+
+	private boolean enableBuilderParser() {
+		return enableBuilderParserButton.getSelection();
+	}
+
+	private boolean enableProviderParser() {
+		return enableProviderParserButton.getSelection();
+	}
+}

Back to the top