Merge commit
authorEd Swartz <ed.swartz@nokia.com>
Thu, 03 Dec 2009 12:04:42 -0600
changeset 612 c43ac80c8d32
parent 611 5d967503c150 (diff)
parent 597 0936494b27b5 (current diff)
child 616 4e541099c2ab
child 627 6b50d727138b
child 641 1f0a706d24b2
Merge commit
--- a/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/builder/DefaultViewParserConfiguration.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/builder/DefaultViewParserConfiguration.java	Thu Dec 03 12:04:42 2009 -0600
@@ -27,6 +27,7 @@
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.IIncludeFileLocator;
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.ITranslationUnitProvider;
 import com.nokia.carbide.cpp.sdk.core.ISymbianBuildContext;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 public class DefaultViewParserConfiguration implements IViewParserConfiguration {
 
@@ -144,6 +145,9 @@
 					// when there's no project and it's local, we just return the drive letter.  for network
 					// paths, I assume we just return the machine name?
 					return bldInfPath.removeLastSegments(bldInfPath.segmentCount()-1);
+				} else if (HostOS.IS_UNIX) {
+					// won't be a base drive
+					return Path.ROOT;
 				}
 			}
 		}
--- a/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/CarbideSBSv2Builder.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/CarbideSBSv2Builder.java	Thu Dec 03 12:04:42 2009 -0600
@@ -33,11 +33,10 @@
 import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
 import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
 import com.nokia.carbide.cpp.internal.api.sdk.SBSv2Utils;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
 
 public class CarbideSBSv2Builder implements ICarbideBuilder {
 
-    private static final IPath SBS = new Path("sbs.bat"); //$NON-NLS-1$
-
     private static final String CLEAN_CMD = "CLEAN"; //$NON-NLS-1$
     private static final String FREEZE_CMD = "FREEZE"; //$NON-NLS-1$
     private static final String REALLYCLEAN_CMD = "REALLYCLEAN"; //$NON-NLS-1$
@@ -45,9 +44,6 @@
     private static final String COMPONENT_ARG = "-p"; //$NON-NLS-1$
     private static final String COMPILE_ARG = "-c"; //$NON-NLS-1$
     
-    private static final IPath SBS_BAT = new Path("sbs.bat"); //$NON-NLS-1$
-    
-    
     public boolean buildAllComponents(ICarbideBuildConfiguration buildConfig, List<IPath> normalMakMakePaths, List<IPath> testMakMakePaths, CarbideCommandLauncher launcher, IProgressMonitor monitor) {
 		
 		SubMonitor progress = SubMonitor.convert(monitor, 3);
@@ -543,7 +539,8 @@
 
 		launcher.writeToConsole("\n***Invoking sbs command\n");
 		
-		int retVal = launcher.executeCommand(SBS, args.toArray(new String[args.size()]), getResolvedEnvVars(buildConfig), cpi.getINFWorkingDirectory());
+		int retVal = launcher.executeCommand(SBSv2Utils.getSBSPath(), 
+				args.toArray(new String[args.size()]), getResolvedEnvVars(buildConfig), cpi.getINFWorkingDirectory());
 		if (retVal != 0) {
 			launcher.writeToConsole("\n=== SBS command failed with error code " + retVal + " ===");
 			launcher.writeToConsole("\n***Stopping. Check the Problems view or Console output for errors.\n");
@@ -582,7 +579,9 @@
 		String[] sbsArgs = new String[] {"--source-target=" + file.toOSString(), COMPILE_ARG, buildTarget, COMPONENT_ARG, fullMMPPath.toFile().getName()};
 		launcher.setErrorParserManager(buildConfig.getCarbideProject().getINFWorkingDirectory(), buildConfig.getErrorParserList());
 		
-		int retVal = launcher.executeCommand(SBS_BAT, sbsArgs, getResolvedEnvVars(buildConfig), workingDirectory);
+		int retVal = launcher.executeCommand(
+				SBSv2Utils.getSBSPath(),
+				sbsArgs, getResolvedEnvVars(buildConfig), workingDirectory);
 		if (retVal != 0) {
 			launcher.writeToConsole("\n=== make failed with error code " + retVal + " ===");
 			launcher.writeToConsole("\n***Stopping. Check the Problems view or Console output for errors.\n");
--- a/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/EnvironmentVarsInfo2.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/EnvironmentVarsInfo2.java	Thu Dec 03 12:04:42 2009 -0600
@@ -24,6 +24,7 @@
 import com.nokia.carbide.cpp.internal.x86build.X86BuildPlugin;
 import com.nokia.carbide.cpp.sdk.core.ISymbianBuildContext;
 import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.TrackedResource;
 
 import org.eclipse.cdt.core.settings.model.ICStorageElement;
@@ -36,6 +37,9 @@
 import java.util.*;
 
 public class EnvironmentVarsInfo2 implements IEnvironmentVarsInfo {
+
+	// NOTE: all the paths below use Win32 paths.  We convert these to Unix format at the end of the
+	// #getResolved...() and #getModified...() methods.
 	
 	private static final String X86_COMP_LINK_FOLDER = "Symbian_Tools\\Command_Line_Tools";
 	
@@ -43,11 +47,12 @@
 	private static final String X86_WIN32SDK_FOLDER = "Symbian_Support\\Win32-x86 Support\\Libraries\\Win32 SDK";
 
 	private static final String X86_LINK_LIB_LIST = "MSL_All_MSE_Symbian_D.lib;gdi32.lib;user32.lib;kernel32.lib;";
-	                                                 
-	private static final String MWCSYM2INCLUDES = "MWCSYM2INCLUDES";
-	private static final String MWSYM2LIBRARIES = "MWSYM2LIBRARIES";
-	private static final String MWSYM2LIBRARYFILES = "MWSYM2LIBRARYFILES";
-	private static final String MWCINCLUDES = "MWCINCLUDES";
+	                        
+	// use host-independent case
+	private static final String MWCSYM2INCLUDES = "MWCSym2Includes";
+	private static final String MWSYM2LIBRARIES = "MWSym2Libraries";
+	private static final String MWSYM2LIBRARYFILES = "MWSym2LibraryFiles";
+	private static final String MWCINCLUDES = "MWCIncludes";
 	private static final String PATH = "PATH";
 	private static final String EPOCROOT = "EPOCROOT";
 	
@@ -123,7 +128,7 @@
 	public IEnvironmentVariable getEnvVarFromConfiguration(String varName) {
 		
 		for (IEnvironmentVariable currVar : envVarsList) {
-			if (currVar.getName().toUpperCase().equals(varName.toUpperCase())) {
+			if (currVar.getName().equalsIgnoreCase(varName)) {
 				return currVar;
 			}
 		}
@@ -229,13 +234,13 @@
 
 					prependValue += currEnvVar.substring(PATH.length() + 1);
 					returnEnvArray[i] = prependValue;
-				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWCSYM2INCLUDES + EQUALS)) {
+				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWCSYM2INCLUDES.toUpperCase() + EQUALS)) {
 						returnEnvArray[i] = MWCSYM2INCLUDES + EQUALS + getMWIncludesEnvString(); 
 					//}
-				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWSYM2LIBRARIES + EQUALS)) {
+				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWSYM2LIBRARIES.toUpperCase() + EQUALS)) {
 						returnEnvArray[i] = MWSYM2LIBRARIES + EQUALS + getMWLibraryIncludesEnvString();
 					
-				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWSYM2LIBRARYFILES + EQUALS)) {
+				} else if ((currEnvVar.toUpperCase() + EQUALS).startsWith(MWSYM2LIBRARYFILES.toUpperCase() + EQUALS)) {
 						returnEnvArray[i] = MWSYM2LIBRARYFILES + EQUALS + getMWLibraryFilesEnvString();
 				}
 				
@@ -352,6 +357,13 @@
 				returnEnvArray = mapToStringArray(varsMap);
 			}
 		}
+		
+		// Fix up the notation in the environment (convert Win32-type variables to Unix-type)
+		if (HostOS.IS_UNIX) {
+			for (int i = 0; i < returnEnvArray.length; i++) {
+				returnEnvArray[i] = HostOS.convertPathListToUnix(returnEnvArray[i]);
+			}
+		}
 
 		return returnEnvArray;
 	}
@@ -372,6 +384,13 @@
 			}
 		}
 		
+		// Fix up the notation in the environment (convert Win32-type variables to Unix-type)
+		if (HostOS.IS_UNIX) {
+			for (int i = 0; i < modifiedVars.length; i++) {
+				modifiedVars[i] = HostOS.convertPathListToUnix(modifiedVars[i]);
+			}
+		}
+		
 		return modifiedVars;
 	}
 	
--- a/core/com.nokia.carbide.bugreport/src/com/nokia/carbide/internal/bugreport/resources/ImageResourceManager.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.bugreport/src/com/nokia/carbide/internal/bugreport/resources/ImageResourceManager.java	Thu Dec 03 12:04:42 2009 -0600
@@ -41,7 +41,7 @@
     	
     	ImageRegistry imgReg = JFaceResources.getImageRegistry();
     	
-    	Image img = new Image( disp, imagesPath + "\\bug_report_with_banner_75x66.png" );  	 //$NON-NLS-1$
+    	Image img = new Image( disp, imagesPath + "/bug_report_with_banner_75x66.png" );  	 //$NON-NLS-1$
         imgReg.put( ImageKeys.WIZARD_BANNER, img );
 	}
 	
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/api/sdk/SBSv2Utils.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/api/sdk/SBSv2Utils.java	Thu Dec 03 12:04:42 2009 -0600
@@ -29,6 +29,7 @@
 
 import com.nokia.carbide.cpp.sdk.core.*;
 import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.Logging;
 
 /**
@@ -42,6 +43,12 @@
 
 	private static List<String> unfilteredSBSv2ConfigNames;
 
+	protected static final String SBS_HOME = "SBS_HOME";
+	protected static String sbsHome;
+	protected static IPath sbsPath;
+
+	private static boolean scannedSbsState = false;
+	private static final String sbsScriptName = HostOS.IS_WIN32 ? "sbs.bat" : "sbs"; 
 	
 	/**
      * Get the path to the SBSv2 bin directory.  This is based on the SBS_HOME environment variable
@@ -220,6 +227,20 @@
 	}
 
 	/**
+	 * Whether or not to display SBSv1 builder UI
+	 * @return true if SBSv1 is available, false otherwise
+	 */
+	public static boolean enableSBSv1Support() {
+		if (!enableSBSv2Support())
+			return true;
+		
+		// TODO LINUX: more accurate check
+		if (HostOS.IS_WIN32)
+			return true;
+		return false;
+	}
+	
+	/**
 	 * Whether or not to display SBSv2 builder UI
 	 * @return true if SBSv2 is installed, false otherwise
 	 */
@@ -276,4 +297,35 @@
 			}
 		}
     }
+
+	/**
+	 * (Re-)scan the SBSv2 / Raptor configuration
+	 * @return message if error, else null
+	 */
+	public static String scanSBSv2() {
+		// do some basic checks
+		sbsHome = System.getenv(SBS_HOME);
+		if (sbsHome == null) {
+			return "Please define the SBS_HOME environment (e.g. /path/to/raptor) and add $SBS_HOME/bin to your PATH before running Carbide.";
+		}
+		
+		sbsPath = HostOS.findProgramOnPath(sbsScriptName, null);
+		if (sbsPath == null) {
+			return "Please add $SBS_HOME/bin to your PATH before running Carbide.";
+		}
+
+		return null;
+	}
+
+    /**
+     * Get the path to SBSv2 (sbs.bat or sbs)
+     */
+	public static IPath getSBSPath() {
+		if (!scannedSbsState) {
+			scanSBSv2();
+			scannedSbsState = true;
+		}
+		return sbsPath != null ? sbsPath : new Path(sbsScriptName);  // dummy
+	}
+
 }
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/api/sdk/SDKManagerInternalAPI.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/api/sdk/SDKManagerInternalAPI.java	Thu Dec 03 12:04:42 2009 -0600
@@ -14,37 +14,37 @@
 
 import java.util.List;
 
-import com.nokia.carbide.cpp.internal.sdk.core.model.SDKManager;
+import com.nokia.carbide.cpp.internal.sdk.core.model.AbstractSDKManager;
 import com.nokia.carbide.cpp.sdk.core.*;
 
 public class SDKManagerInternalAPI {
 	    
     public static ISymbianSDK addMissingSdk(String uid) {
-    	return ((SDKManager)SDKCorePlugin.getSDKManager()).addMissingSdk(uid);
+    	return ((AbstractSDKManager)SDKCorePlugin.getSDKManager()).addMissingSdk(uid);
     }
     
     public static void removeMissingSdk(String uid) {
-    	((SDKManager)SDKCorePlugin.getSDKManager()).removeMissingSdk(uid);
+    	((AbstractSDKManager)SDKCorePlugin.getSDKManager()).removeMissingSdk(uid);
     }
     
     public static ISymbianSDK getMissingSdk(String uid) {
-    	return ((SDKManager)SDKCorePlugin.getSDKManager()).getMissingSdk(uid);
+    	return ((AbstractSDKManager)SDKCorePlugin.getSDKManager()).getMissingSdk(uid);
     }
     
 	public static List<ISymbianSDK> getMissingSDKList() {
-		return ((SDKManager)SDKCorePlugin.getSDKManager()).getMissingSDKList();			
+		return ((AbstractSDKManager)SDKCorePlugin.getSDKManager()).getMissingSDKList();			
 	}
 
 	public static void addInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
-		((SDKManager)SDKCorePlugin.getSDKManager()).addInstalledSdkChangeListener(listener);
+		((AbstractSDKManager)SDKCorePlugin.getSDKManager()).addInstalledSdkChangeListener(listener);
 	}
 	
 	public static void removeInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
-		((SDKManager)SDKCorePlugin.getSDKManager()).removeInstalledSdkChangeListener(listener);
+		((AbstractSDKManager)SDKCorePlugin.getSDKManager()).removeInstalledSdkChangeListener(listener);
 	}
 	
 	public static void fireInstalledSdkChanged(ICarbideInstalledSDKChangeListener.SDKChangeEventType eventType) {
-		((SDKManager)SDKCorePlugin.getSDKManager()).fireInstalledSdkChanged(eventType);
+		((AbstractSDKManager)SDKCorePlugin.getSDKManager()).fireInstalledSdkChanged(eventType);
 	}
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/AbstractSDKManager.java	Thu Dec 03 12:04:42 2009 -0600
@@ -0,0 +1,691 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+*/
+package com.nokia.carbide.cpp.internal.sdk.core.model;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.Version;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeIterator;
+import org.xml.sax.SAXException;
+
+import com.nokia.carbide.cpp.internal.api.sdk.BuildPlat;
+import com.nokia.carbide.cpp.internal.api.sdk.ICarbideDevicesXMLChangeListener;
+import com.nokia.carbide.cpp.internal.api.sdk.ISDKManagerInternal;
+import com.nokia.carbide.cpp.internal.api.sdk.SBSv2Utils;
+import com.nokia.carbide.cpp.internal.api.sdk.SDKManagerInternalAPI;
+import com.nokia.carbide.cpp.internal.api.sdk.SymbianMacroStore;
+import com.nokia.carbide.cpp.sdk.core.ICarbideInstalledSDKChangeListener;
+import com.nokia.carbide.cpp.sdk.core.IRVCTToolChainInfo;
+import com.nokia.carbide.cpp.sdk.core.ISDKManager;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+import com.nokia.carbide.cpp.sdk.core.ICarbideInstalledSDKChangeListener.SDKChangeEventType;
+import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
+import com.nokia.cpp.internal.api.utils.core.ListenerList;
+import com.nokia.cpp.internal.api.utils.core.Logging;
+import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
+import com.sun.org.apache.xpath.internal.XPathAPI;
+
+public abstract class AbstractSDKManager implements ISDKManager, ISDKManagerInternal {
+	
+	protected static List<ISymbianSDK> sdkList = new ArrayList<ISymbianSDK>();
+	protected HashMap<String,ISymbianSDK> missingSdkMap = new HashMap<String,ISymbianSDK>();
+
+	protected static final String CARBIDE_SDK_CACHE_FILE_NAME = "carbideSDKCache.xml";
+	protected static final String SDK_CACHE_ID_ATTRIB = "id";
+	protected static final String SDK_CACHE_ENABLED_ATTRIB = "isEnabled";
+	protected static final String SDK_CACHE_OS_VERSION_ATTRIB = "osVersion";
+	protected static final String SDK_CACHE_OS_BRANCH_ATTRIB = "osBranch";
+	protected static final String SDK_CACHE_SDK_VERSION_ATTRIB = "sdkVersion";
+	protected static final String SDK_SCANNED_FOR_PLUGINS = "sdkScanned";
+
+	protected static final String SDK_CACHE_EPOCROOT_ATTRIB = "epocroot";
+
+	protected static final String EMPTY_STRING = "";
+	protected static boolean enableBSFScanner;
+	protected static List<BuildPlat> platList = new ArrayList<BuildPlat>();
+	protected static SymbianMacroStore macroStore;
+	
+	protected static final String[] knownRVCTVersions = {"3.1", "3.0", "2.2", "2.1"};
+	protected Version sbsV2Version;
+	
+	/**
+	 * Minimum SBSv2 version supported with Carbide
+	 */
+	public static final Version MINIMUM_RAPTOR_VERSION = new Version(2, 8, 6);
+
+	static boolean hasScannedSDKs = false; // make sure we only scan SDKs when needed
+	
+	protected static List<IRVCTToolChainInfo> rvctInfoList = null;
+	
+	/**
+	 * Implement listener so other class that use this can listen to SDK 
+	 * change event (e.g. validate project config description)
+	 */
+	protected static ListenerList<ICarbideInstalledSDKChangeListener> listeners = new ListenerList<ICarbideInstalledSDKChangeListener>();
+	
+	/*
+	 * Implement listener so other class that use this can listen for when a change to the devices.xml
+	 * has been modified outside of Carbide
+	 */
+	protected static ListenerList<ICarbideDevicesXMLChangeListener> devicesXMLListeners = new ListenerList<ICarbideDevicesXMLChangeListener>();
+	
+	
+	public AbstractSDKManager() {
+		macroStore = SymbianMacroStore.getInstance();
+	}
+	
+	public SymbianMacroStore getSymbianMacroStore(){
+		return macroStore;
+	}
+	
+	public void scanSDKs() {
+		synchronized (sdkList)
+		{
+			ArrayList<ISymbianSDK> oldSDkList = new ArrayList<ISymbianSDK>(sdkList);
+			
+			getSBSv2Version(true);
+			
+			if (sdkList != null){
+				sdkList.clear();
+			}
+		
+			if (!doScanSDKs())
+				return;
+			
+			// now these SDK's are newly added, remove from internal list
+			for (ISymbianSDK sdk : sdkList) {
+				if (SDKManagerInternalAPI.getMissingSdk(sdk.getUniqueId()) != null) {
+					SDKManagerInternalAPI.removeMissingSdk(sdk
+							.getUniqueId());
+				}
+			}
+
+			// now these SDK's are removed from the old list, add to
+			// internal list
+			for (ISymbianSDK oldSdk : oldSDkList) {
+				boolean found = false;
+				for (ISymbianSDK sdk : sdkList) {
+					if (sdk.getUniqueId().equals(oldSdk.getUniqueId())) {
+						found = true;
+						break;
+					}
+				}
+				if (found == false) {
+					SDKManagerInternalAPI.addMissingSdk(oldSdk
+							.getUniqueId());
+				}
+			}
+
+
+		}
+
+		// make sure we don't rescan over and over again
+		hasScannedSDKs = true;
+		
+		// tell others about it
+		fireInstalledSdkChanged(SDKChangeEventType.eSDKScanned);
+		scanCarbideSDKCache();
+	}
+
+	/**
+	 * Actually scan the SDKs available and populate sdkList.   
+	 * @param oldSDkList old list of SDKs available for reference, e.g., detecting
+	 * when SDKs are newly missing
+	 * @return
+	 */
+	abstract protected boolean doScanSDKs();
+	
+
+	protected void ensureScannedSDKs() {
+		if (!hasScannedSDKs) {
+			scanSDKs();
+		}
+	}
+	
+	public List<ISymbianSDK> getSDKList() {
+		
+		synchronized(sdkList)
+		{
+			if (sdkList.size() < 1) {
+				ensureScannedSDKs();
+			}
+			List<ISymbianSDK> listCopy = new ArrayList<ISymbianSDK>(sdkList);
+			return listCopy;			
+		}
+	}
+
+	public ISymbianSDK getSDK(String sdkId, boolean scanIfNecessary) {
+		if (scanIfNecessary) {
+			getSDKList();
+		}
+		synchronized(sdkList)
+		{
+			for (Iterator iter = sdkList.iterator(); iter.hasNext();) {
+				ISymbianSDK sdk = (ISymbianSDK)iter.next();
+				if (sdk.getUniqueId().compareTo(sdkId) == 0) {
+					return sdk;
+				}
+			}
+		}
+		return null;
+	}
+
+	
+	public void addSDK(ISymbianSDK sdk) {
+		synchronized(sdkList)
+		{
+			try {
+				updateSDK(sdk);
+				sdkList.add(sdk);
+				SDKManagerInternalAPI.removeMissingSdk(sdk.getUniqueId());
+				// tell others about it
+				fireInstalledSdkChanged(SDKChangeEventType.eSDKAdded);
+			}
+			catch (Exception e) {
+				logError("Could not add SDK", e);
+				String message = "Could not add this SDK. Your devices.xml file may be corrupt. If you remove the file from its current location and then rescan SDKs, Carbide will offer to create a new one.";
+				Logging.showErrorDialog(WorkbenchUtils.getSafeShell(), null, message, Logging.newSimpleStatus(1, e));
+			}
+		}
+	}
+	
+	public boolean removeSDK(String sdkId) {
+		synchronized (sdkList)
+		{
+			if (sdkList != null){
+				for (ISymbianSDK currSDK : sdkList){
+					if (currSDK.getUniqueId().equals(sdkId)){
+						sdkList.remove(currSDK);
+						
+						SDKManagerInternalAPI.addMissingSdk(currSDK.getUniqueId());
+						
+						// tell others about it
+						fireInstalledSdkChanged(SDKChangeEventType.eSDKRemoved);
+						
+						doRemoveSDK(sdkId);
+						
+						break;
+					}
+				}
+				
+				updateCarbideSDKCache();
+				
+			} else {
+				return false;
+			}			
+		}
+		return true;
+	}
+
+	abstract protected boolean doRemoveSDK(String sdkId);
+
+	protected void scanCarbideSDKCache(){
+		
+		DocumentBuilder docBuilder = null;
+		try {
+			docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		} catch (ParserConfigurationException e) {
+			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+			throw new RuntimeException(e);
+		}
+		
+		// NOTE: If debugging runtime workbench and you clear your configuraiton at each launch
+		// the data in the configuration location will be lost
+		Location configurationLocation = Platform.getConfigurationLocation();
+		try {
+			URL url = new URL(configurationLocation.getURL(), SDKCorePlugin.PLUGIN_ID);
+			File configFolder = new File(url.getFile());
+			if (!configFolder.exists()) {
+				configFolder.mkdirs();
+			}
+
+		    File carbideSDKCacheFile = new File(configFolder, CARBIDE_SDK_CACHE_FILE_NAME);
+		    if (!carbideSDKCacheFile.exists()){
+		    	try {
+		    	FileUtils.writeFileContents(carbideSDKCacheFile, EMPTY_STRING.toCharArray(), null);
+		    	} catch (CoreException e){
+		    		e.printStackTrace();
+		    	}
+		    }else if (carbideSDKCacheFile.length() > 0) {
+			Document lastKnownDoc = docBuilder.parse(carbideSDKCacheFile);
+			
+			NodeIterator ni = XPathAPI.selectNodeIterator(lastKnownDoc, "/sdks/sdk");
+			for (Node n = ni.nextNode(); n != null; n = ni.nextNode()) {
+				
+				// get the unique ID
+				NamedNodeMap attribs = n.getAttributes();
+				String id = attribs.getNamedItem(SDK_CACHE_ID_ATTRIB).getNodeValue();
+				
+				// get whether or not the SDK is enabled
+				String sdkEnabled = "true";
+				Node sdkEnabledItem = attribs.getNamedItem(SDK_CACHE_ENABLED_ATTRIB);
+				if (sdkEnabledItem != null)
+					sdkEnabled = sdkEnabledItem.getNodeValue();
+				
+				// get the os version
+				String osVersion = "";
+				Node osVersionItem = attribs.getNamedItem(SDK_CACHE_OS_VERSION_ATTRIB);
+				if (osVersionItem != null)
+					osVersion = osVersionItem.getNodeValue();
+				
+				// get the os branch
+				String osBranch = "";
+				Node osBranchItem = attribs.getNamedItem(SDK_CACHE_OS_BRANCH_ATTRIB);
+				if (osBranchItem != null)
+					osBranch = osBranchItem.getNodeValue();
+				
+				// get the sdk version
+				String sdkVersion = "";
+				Node sdkVersionItem = attribs.getNamedItem(SDK_CACHE_SDK_VERSION_ATTRIB);
+				if (sdkVersionItem != null)
+					sdkVersion = sdkVersionItem.getNodeValue();
+				
+				// get the custom EPOCROOT, if allowed
+				String customEpocroot = null;
+				if (!isEPOCRootFixed()) {
+					Node epocrootItem = attribs.getNamedItem(SDK_CACHE_EPOCROOT_ATTRIB);
+					if (epocrootItem != null)
+						customEpocroot = epocrootItem.getNodeValue();
+				}
+				
+				// get whether or not this SDK has been scanned
+				String wasScanned = "false";
+				Node sdkScannedItem = attribs.getNamedItem(SDK_SCANNED_FOR_PLUGINS);
+				if (sdkScannedItem != null)
+					wasScanned = sdkScannedItem.getNodeValue();
+				
+				ISymbianSDK sdk = getSDK(id, false);
+				if (sdk != null){
+					
+					if (wasScanned.equalsIgnoreCase("true")){
+						sdk.setPreviouslyScanned(true);
+					} else {
+						sdk.setPreviouslyScanned(false);
+					}
+					
+					if (sdkEnabled.equalsIgnoreCase("true")){
+						sdk.setEnabled(true);
+					} else {
+						sdk.setEnabled(false);
+					}
+					
+					if (!osVersion.equals("")){
+						if (Version.parseVersion(osVersion).getMajor() != 0){
+							sdk.setOSVersion(Version.parseVersion(osVersion));
+						}
+					}
+					
+					if (!osBranch.equals("")){
+						sdk.setOSSDKBranch(osBranch);
+					}
+					
+					if (!sdkVersion.equals("")){
+						if (Version.parseVersion(sdkVersion).getMajor() != 0){
+							sdk.setSDKVersion(Version.parseVersion(sdkVersion));
+						}
+					}
+					
+					if (customEpocroot != null) {
+						sdk.setEPOCROOT(customEpocroot);
+					}
+					
+				}
+				
+			} // for
+		} 
+	} catch (TransformerException e) {
+	} catch (SAXException e) {
+	} catch (IOException e) {
+	}
+	}
+	
+	public void updateCarbideSDKCache() {
+		if (!Platform.isRunning())
+			return;
+			
+		DocumentBuilder docBuilder = null;
+		try {
+			docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		} catch (ParserConfigurationException e) {
+			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+			return;
+		}
+		
+		Location configurationLocation = Platform.getConfigurationLocation();
+		try {
+					
+			URL url = new URL(configurationLocation.getURL(), SDKCorePlugin.PLUGIN_ID);
+			File configFolder = new File(url.getFile());
+			if (!configFolder.exists()) {
+				configFolder.mkdirs();
+			}
+			
+			File carbideSDKCacheFile = new File(configFolder, CARBIDE_SDK_CACHE_FILE_NAME);
+		    if (!carbideSDKCacheFile.exists()){
+		    	try {
+		    	FileUtils.writeFileContents(carbideSDKCacheFile, EMPTY_STRING.toCharArray(), null);
+		    	} catch (CoreException e){
+		    		e.printStackTrace();
+		    	}
+		    }
+		    
+			Document d = docBuilder.newDocument();
+			Node sdks = d.appendChild(d.createElement("sdks"));
+				
+			synchronized(sdkList)
+			{
+				for (ISymbianSDK currSDK: sdkList) {
+					Node sdk = sdks.appendChild(d.createElement("sdk"));
+					NamedNodeMap attribs = sdk.getAttributes();
+					Node idNode = d.createAttribute(SDK_CACHE_ID_ATTRIB);
+					idNode.setNodeValue(currSDK.getUniqueId());
+					attribs.setNamedItem(idNode);
+						
+					// Hide the build config from view in the build config list?
+					Node enabledNode = d.createAttribute(SDK_CACHE_ENABLED_ATTRIB);
+					if (true == currSDK.isEnabled()) {
+						enabledNode.setNodeValue("true");
+					} else {
+						enabledNode.setNodeValue("false");
+					}
+					attribs.setNamedItem(enabledNode);
+					
+					Node wasScannedNode = d.createAttribute(SDK_SCANNED_FOR_PLUGINS);
+					if (true == currSDK.isPreviouslyScanned()) {
+						wasScannedNode.setNodeValue("true");
+					} else {
+						wasScannedNode.setNodeValue("false");
+					}
+					attribs.setNamedItem(wasScannedNode);
+					
+					Node osVerNode = d.createAttribute(SDK_CACHE_OS_VERSION_ATTRIB);
+					osVerNode.setNodeValue(currSDK.getOSVersion().toString());
+					attribs.setNamedItem(osVerNode);
+					
+					Node osBranchNode = d.createAttribute(SDK_CACHE_OS_BRANCH_ATTRIB);
+					osBranchNode.setNodeValue(currSDK.getSDKOSBranch());
+					attribs.setNamedItem(osBranchNode);
+					
+					Node sdkVerNode = d.createAttribute(SDK_CACHE_SDK_VERSION_ATTRIB);
+					sdkVerNode.setNodeValue(currSDK.getSDKVersion().toString());
+					attribs.setNamedItem(sdkVerNode);
+					
+					if (!isEPOCRootFixed()) {
+						Node sdkEpocRootNode = d.createAttribute(SDK_CACHE_EPOCROOT_ATTRIB);
+						sdkEpocRootNode.setNodeValue(currSDK.getEPOCROOT());
+						attribs.setNamedItem(sdkEpocRootNode);
+					}
+				}
+			}
+			DOMSource domSource = new DOMSource(d);
+			TransformerFactory transFactory = TransformerFactory.newInstance();
+			Result fileResult = new StreamResult(carbideSDKCacheFile);
+			try {
+				transFactory.newTransformer().transform(domSource, fileResult);
+			} catch (TransformerConfigurationException e) {
+				ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+			} catch (TransformerException e) {
+				ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+			} 
+		} catch (MalformedURLException e){
+			
+		}
+	}
+
+	/**
+	 * Tell whether EPOCROOT can be changed for a given ISymbianSDK
+	 * @return flag
+	 */
+	abstract protected boolean isEPOCRootFixed();
+
+	public boolean getBSFScannerEnabled(){
+		return enableBSFScanner;
+	}
+	
+	public void enableBSFScanner(boolean enabled){
+		enableBSFScanner = enabled;
+	}
+	
+	public void setPlatformList(List<BuildPlat> inPlatList){
+		platList = inPlatList;
+	}
+	
+	public List<BuildPlat> getPlatformList(){
+		return platList;
+	}
+
+	public synchronized IRVCTToolChainInfo[] getInstalledRVCTTools() {
+		// the path wn't change inside one invocation so cache the results
+		if (rvctInfoList == null) {
+			rvctInfoList = scanForInstalledRVCTCompilers();
+		}
+		return (IRVCTToolChainInfo[]) rvctInfoList.toArray(new IRVCTToolChainInfo[rvctInfoList.size()]);
+	}
+	
+	/**
+	 * Get a list of IRVCTToolChainInfo objects for all RVCT installations detected on the PATH env var.
+	 */
+	protected static List<IRVCTToolChainInfo> scanForInstalledRVCTCompilers() {
+		
+		Runtime rt=Runtime.getRuntime();
+		List<IRVCTToolChainInfo> rvctToolList = new ArrayList<IRVCTToolChainInfo>();
+		
+		IPath[] pathEntries = HostOS.getPathEntries(null);
+		
+		for(IPath path : pathEntries) {
+			try {
+				String command = path.append("armcc").toOSString() + " --vsn";
+				
+				Process p = rt.exec(command);
+				
+				BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+				
+				String overallOutput = null;
+				String stdErrLine = null;
+
+				// RVCT waits for like 4 minutes trying to find a license when the computer is
+				// not connected to the network.  in such cases, the call to br.readline doesn't
+				// return for 4 minutes which is unacceptable here.  Instead we'll poll at 1/2 second
+				// intervals for 40 seconds and see if we get a response. On the first response we break out
+				// of the loop and read the output. So in most normal circumstances it will take 1/2 to 1 seconds.
+				int maxTries = 80;
+				int numTries = 0;
+				while (numTries < maxTries) {
+					try {
+						Thread.sleep(500);
+					} catch (InterruptedException e) {
+						// ignore
+					}
+					if (br.ready()) {
+						while ((stdErrLine = br.readLine()) != null) {
+							overallOutput += stdErrLine;
+						}
+						break;
+					}
+					numTries++;
+				}
+				
+				p.destroy();
+				
+				if (overallOutput != null && overallOutput.length() > 0){
+					for (String currVersion : knownRVCTVersions) {
+						
+						if(overallOutput.contains(currVersion)) {
+							RVCTToolChainInfo rvctInfo = new RVCTToolChainInfo();
+							rvctInfo.setRvctToolBinariesDirectory(path.toOSString());
+							rvctInfo.setRvctToolsVersion(new Version(currVersion));
+							rvctToolList.add(rvctInfo);
+							break; // tool successfully added
+						}
+					}
+				}
+			}
+			catch (IOException e) {
+				// armcc isn't in this directory, ignore....
+			}
+		}
+				
+		return rvctToolList;
+	}
+	
+    public ISymbianSDK addMissingSdk(String uid) {
+		ISymbianSDK sdk = getMissingSdk(uid);
+		if (sdk == null) {
+			sdk = SymbianMissingSDKFactory.createInstance(uid);
+			missingSdkMap.put(uid, sdk);
+		}
+    	return sdk;
+    }
+    
+    public void removeMissingSdk(String uid) {
+    	missingSdkMap.remove(uid);
+    }
+    
+    public ISymbianSDK getMissingSdk(String uid) {
+    	return missingSdkMap.get(uid);
+    }
+    
+	public List<ISymbianSDK> getMissingSDKList() {
+		List<ISymbianSDK> listCopy = new ArrayList<ISymbianSDK>();
+		synchronized(missingSdkMap) {
+			for (ISymbianSDK sdk : missingSdkMap.values()) {
+				listCopy.add(sdk);
+			}
+		}
+		return listCopy;			
+	}
+	
+	public void addInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
+		listeners.add(listener);
+	}
+	
+	public void removeInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
+		listeners.remove(listener);
+	}
+	
+	public void fireInstalledSdkChanged(SDKChangeEventType eventType) {
+		for (ICarbideInstalledSDKChangeListener l : listeners) {
+			l.installedSdkChanged(eventType);
+		}
+	}
+	
+	public void addDevicesXMLChangeListener(ICarbideDevicesXMLChangeListener listener) {
+		devicesXMLListeners.add(listener);
+	}
+	
+	public void removeDevicesXMLChangeListener(ICarbideDevicesXMLChangeListener listener) {
+		devicesXMLListeners.remove(listener);
+	}
+	
+	public void fireDevicesXMLChanged() {
+		for (ICarbideDevicesXMLChangeListener l : devicesXMLListeners) {
+			l.devicesXMLOutOfSync();
+		}
+	}
+	
+	protected void logError(String message, Throwable t) {
+		SDKCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.getPluginId(), message, t));		
+	}
+
+	public Version getSBSv2Version(boolean forceScan) {
+		if (sbsV2Version == null || forceScan){
+			sbsV2Version = new Version(0, 0, 0);
+			
+			Runtime rt=Runtime.getRuntime();
+			try {
+				IPath sbsPath = SBSv2Utils.getSBSPath();
+				Process p = rt.exec(new String[] { sbsPath.toOSString(), "-v" });
+				
+				BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+				String overallOutput = null;
+				String stdErrLine = null;
+				while ((stdErrLine = br.readLine()) != null) {
+					overallOutput += stdErrLine;
+				}
+				
+				if (overallOutput != null) {
+				{
+					String[] tokens = overallOutput.split(" ");
+					if (tokens.length >= 3) {
+						if (tokens[2].split("\\.").length == 3) {
+							sbsV2Version = Version.parseVersion(tokens[2]);
+						}
+					}
+						if (sbsV2Version.compareTo(MINIMUM_RAPTOR_VERSION) < 0 && sbsV2Version.getMajor() > 0) {
+
+							String incorrectRaptorVersionStr = "SBSv2 version detected: "
+									+ sbsV2Version.toString()
+									+ ". The minimum version suggested for Carbide is: "
+									+ MINIMUM_RAPTOR_VERSION.getMajor()
+									+ "."
+									+ MINIMUM_RAPTOR_VERSION.getMinor()
+									+ "."
+									+ MINIMUM_RAPTOR_VERSION.getMicro();
+
+							ResourcesPlugin.getPlugin().getLog().log(
+									new Status(IStatus.WARNING,
+											SDKCorePlugin.PLUGIN_ID,
+											IStatus.WARNING,
+											incorrectRaptorVersionStr, null));
+						}
+					
+					p.destroy();
+				}
+			}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			
+			
+			
+		}
+		return sbsV2Version;
+	}
+
+	public Version getMinimumSupportedSBSv2Version() {
+		return MINIMUM_RAPTOR_VERSION;
+	}
+	
+	
+}
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManager.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManager.java	Thu Dec 03 12:04:42 2009 -0600
@@ -19,71 +19,33 @@
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
-import java.net.URL;
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Result;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
 import org.eclipse.cdt.utils.WindowsRegistry;
 import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
 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.Status;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.osgi.service.datalocation.Location;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
-import org.osgi.framework.Version;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.traversal.NodeIterator;
-import org.xml.sax.SAXException;
 
-import com.nokia.carbide.cpp.internal.api.sdk.BuildPlat;
-import com.nokia.carbide.cpp.internal.api.sdk.ICarbideDevicesXMLChangeListener;
-import com.nokia.carbide.cpp.internal.api.sdk.ISDKManagerInternal;
-import com.nokia.carbide.cpp.internal.api.sdk.SDKManagerInternalAPI;
-import com.nokia.carbide.cpp.internal.api.sdk.SymbianMacroStore;
 import com.nokia.carbide.cpp.internal.sdk.core.gen.Devices.DeviceType;
 import com.nokia.carbide.cpp.internal.sdk.core.gen.Devices.DevicesType;
 import com.nokia.carbide.cpp.internal.sdk.core.xml.DevicesLoader;
-import com.nokia.carbide.cpp.sdk.core.ICarbideInstalledSDKChangeListener;
-import com.nokia.carbide.cpp.sdk.core.IRVCTToolChainInfo;
-import com.nokia.carbide.cpp.sdk.core.ISDKManager;
 import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
 import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
 import com.nokia.carbide.cpp.sdk.core.SDKEnvInfoFailureException;
-import com.nokia.carbide.cpp.sdk.core.ICarbideInstalledSDKChangeListener.SDKChangeEventType;
-import com.nokia.cpp.internal.api.utils.core.FileUtils;
-import com.nokia.cpp.internal.api.utils.core.ListenerList;
-import com.nokia.cpp.internal.api.utils.core.Logging;
 import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
-import com.sun.org.apache.xpath.internal.XPathAPI;
-import com.sun.org.apache.xpath.internal.operations.Minus;
 
-public class SDKManager implements ISDKManager, ISDKManagerInternal {
+public class SDKManager extends AbstractSDKManager {
 	
-	private static List<ISymbianSDK> sdkList = new ArrayList<ISymbianSDK>();
-	private HashMap<String,ISymbianSDK> missingSdkMap = new HashMap<String,ISymbianSDK>();
-
 	private static final String SYMBIAN_COMMON_REG_PATH = "SOFTWARE\\Symbian\\EPOC SDKs\\";
 	private static final String SYMBIAN_COMMON_PATH = "CommonPath";
 	
@@ -92,35 +54,9 @@
 
 	private static final String EMPTY_DEVICES_XML_CONTENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><devices version=\"1.0\"></devices>";
 	
-	private static final String CARBIDE_SDK_CACHE_FILE_NAME = "carbideSDKCache.xml";
-	private static final String SDK_CACHE_ID_ATTRIB = "id";
-	private static final String SDK_CACHE_ENABLED_ATTRIB = "isEnabled";
-	private static final String SDK_CACHE_OS_VERSION_ATTRIB = "osVersion";
-	private static final String SDK_CACHE_OS_BRANCH_ATTRIB = "osBranch";
-	private static final String SDK_CACHE_SDK_VERSION_ATTRIB = "sdkVersion";
-	private static final String SDK_SCANNED_FOR_PLUGINS = "sdkScanned";
-	
-	private static final String EMPTY_STRING = "";
-	private static boolean enableBSFScanner;
-	private static List<BuildPlat> platList = new ArrayList<BuildPlat>();
-	private static SymbianMacroStore macroStore;
-	
-	private static final String[] knownRVCTVersions = {"3.1", "3.0", "2.2", "2.1"};
-	private Version sbsV2Version;
-	
-	/**
-	 * Minimum SBSv2 version supported with Carbide
-	 */
-	public static final Version MINIMUM_RAPTOR_VERSION = new Version(2, 8, 6);
-
-	
-	
 	static boolean hasPromptedForDevicesXML = false; // make sure we only ask once at startup if devices.xml does not exist
-	static boolean hasScannedSDKs = false; // make sure we only scan SDKs when needed
 	long devicesXLMLastModified;
 	
-	private static List<IRVCTToolChainInfo> rvctInfoList = null;
-	
 	/**
 	 * Registry key location for checking CSL (GCCE) Arm Toolchain installation directory. 
 	 */
@@ -131,138 +67,44 @@
 	 */
 	private static final String CSL_ARM_TOOLCHAIN_REG_KEY="InstallLocation";
 	
-	/**
-	 * Implement listener so other class that use this can listen to SDK 
-	 * change event (e.g. validate project config description)
-	 */
-	private static ListenerList<ICarbideInstalledSDKChangeListener> listeners = new ListenerList<ICarbideInstalledSDKChangeListener>();
-	
-	/*
-	 * Implement listener so other class that use this can listen for when a change to the devices.xml
-	 * has been modified outside of Carbide
-	 */
-	private static ListenerList<ICarbideDevicesXMLChangeListener> devicesXMLListeners = new ListenerList<ICarbideDevicesXMLChangeListener>();
-	
-	
 	public SDKManager() {
-		macroStore = SymbianMacroStore.getInstance();
-		
+		super();
 		checkPerlInstallation();
 		
 	}
 	
-	public SymbianMacroStore getSymbianMacroStore(){
-		return macroStore;
-	}
-	
-	public void scanSDKs() {
-		synchronized (sdkList)
-		{
-			ArrayList<ISymbianSDK> oldSDkList = new ArrayList<ISymbianSDK>(sdkList);
-			
-			getSBSv2Version(true);
-			
-			if (sdkList != null){
-				sdkList.clear();
-			}
-			DevicesType devicesType;
-			try {
-				File devicesFile = getDevicesXMLFile();
-
-				if (devicesFile == null || !devicesFile.exists()) {
-					// There is no devices.xml. Ask the user if he/she wants to
-					// add it
-					if (hasPromptedForDevicesXML == false) {
-						hasPromptedForDevicesXML = true;
-						doAsynchPromptCreateDevicesXML();
-					}
-					return; // no devices.xml file..
-				}
-
-				devicesXLMLastModified = devicesFile.lastModified();
-				devicesType = DevicesLoader.loadDevices(devicesFile.toURL());
-				EList devices = devicesType.getDevice();
-				for (Iterator iter = devices.iterator(); iter.hasNext();) {
-					SymbianSDK sdk = new SymbianSDK((DeviceType) iter.next());
-					sdkList.add(sdk);
-				}
-
-				// now these SDK's are newly added, remove from internal list
-				for (ISymbianSDK sdk : sdkList) {
-					if (SDKManagerInternalAPI.getMissingSdk(sdk.getUniqueId()) != null) {
-						SDKManagerInternalAPI.removeMissingSdk(sdk
-								.getUniqueId());
-					}
-				}
+	protected boolean doScanSDKs() {
+		
+		DevicesType devicesType;
+		try {
+			File devicesFile = getDevicesXMLFile();
 
-				// now these SDK's are removed from the old list, add to
-				// internal list
-				for (ISymbianSDK oldSdk : oldSDkList) {
-					boolean found = false;
-					for (ISymbianSDK sdk : sdkList) {
-						if (sdk.getUniqueId().equals(oldSdk.getUniqueId())) {
-							found = true;
-							break;
-						}
-					}
-					if (found == false) {
-						SDKManagerInternalAPI.addMissingSdk(oldSdk
-								.getUniqueId());
-					}
+			if (devicesFile == null || !devicesFile.exists()) {
+				// There is no devices.xml. Ask the user if he/she wants to
+				// add it
+				if (hasPromptedForDevicesXML == false) {
+					hasPromptedForDevicesXML = true;
+					doAsynchPromptCreateDevicesXML();
 				}
-
-			} catch (MalformedURLException e) {
-				e.printStackTrace();
-			} catch (URISyntaxException e) {
-				e.printStackTrace();
-			} catch (IOException e) {
-				e.printStackTrace();
+				return false; // no devices.xml file..
 			}
-		}
-
-		// make sure we don't rescan over and over again
-		hasScannedSDKs = true;
-		
-		// tell others about it
-		fireInstalledSdkChanged(SDKChangeEventType.eSDKScanned);
-		scanCarbideSDKCache();
-	}
 
-	private void ensureScannedSDKs() {
-		if (!hasScannedSDKs) {
-			scanSDKs();
-		}
-	}
-	
-	public List<ISymbianSDK> getSDKList() {
-		
-		synchronized(sdkList)
-		{
-			if (sdkList.size() < 1) {
-				ensureScannedSDKs();
+			devicesXLMLastModified = devicesFile.lastModified();
+			devicesType = DevicesLoader.loadDevices(devicesFile.toURL());
+			EList devices = devicesType.getDevice();
+			for (Iterator iter = devices.iterator(); iter.hasNext();) {
+				SymbianSDK sdk = new SymbianSDK((DeviceType) iter.next());
+				sdkList.add(sdk);
 			}
-			List<ISymbianSDK> listCopy = new ArrayList<ISymbianSDK>(sdkList);
-			return listCopy;			
+
+			return true;
+		} catch (Exception e) {
+			logError("Failed to scan SDKs", e);
+			return false;
 		}
 	}
 
-	public ISymbianSDK getSDK(String sdkId, boolean scanIfNecessary) {
-		if (scanIfNecessary) {
-			getSDKList();
-		}
-		synchronized(sdkList)
-		{
-			for (Iterator iter = sdkList.iterator(); iter.hasNext();) {
-				ISymbianSDK sdk = (ISymbianSDK)iter.next();
-				if (sdk.getUniqueId().compareTo(sdkId) == 0) {
-					return sdk;
-				}
-			}
-		}
-		return null;
-	}
 
-	
 	public void updateSDK(ISymbianSDK sdk) {
 		try {
 			File devicesFile = getDevicesXMLFile();
@@ -278,24 +120,6 @@
 		}
 	}
 	
-	public void addSDK(ISymbianSDK sdk) {
-		synchronized(sdkList)
-		{
-			try {
-				updateSDK(sdk);
-				sdkList.add(sdk);
-				SDKManagerInternalAPI.removeMissingSdk(sdk.getUniqueId());
-				// tell others about it
-				fireInstalledSdkChanged(SDKChangeEventType.eSDKAdded);
-			}
-			catch (Exception e) {
-				logError("Could not add SDK", e);
-				String message = "Could not add this SDK. Your devices.xml file may be corrupt. If you remove the file from its current location and then rescan SDKs, Carbide will offer to create a new one.";
-				Logging.showErrorDialog(WorkbenchUtils.getSafeShell(), null, message, Logging.newSimpleStatus(1, e));
-			}
-		}
-	}
-	
 	public void setDefaultSDK(ISymbianSDK sdk){
 		try {
 			File devicesFile = getDevicesXMLFile();
@@ -322,56 +146,31 @@
 	}
 
 	
-	public boolean removeSDK(String sdkId) {
-		synchronized (sdkList)
-		{
-			if (sdkList != null){
-				for (ISymbianSDK currSDK : sdkList){
-					if (currSDK.getUniqueId().equals(sdkId)){
-						sdkList.remove(currSDK);
-						
-						SDKManagerInternalAPI.addMissingSdk(currSDK.getUniqueId());
-						
-						// tell others about it
-						fireInstalledSdkChanged(SDKChangeEventType.eSDKRemoved);
-						
-						// Now actually remove it from the file...
-						DevicesType devicesType;
-						try {
-							File devicesFile = getDevicesXMLFile();
-							 
-							// if file does not exist, let exception cath it...
-							devicesType = DevicesLoader.loadDevices(devicesFile.toURL());
-							EList devices = devicesType.getDevice();
-							for (Iterator iter = devices.iterator(); iter.hasNext();) {
-								DeviceType device = (DeviceType)iter.next();
-								if (device.getId().equals(sdkId)){
-									if (!DevicesLoader.deleteDeviceEntry(device, devicesFile.toURL())){
-										return false; // write failed
-									}
-									break;
-								}
-							}
-						} catch (MalformedURLException e) {
-							e.printStackTrace();
-						} catch (URISyntaxException e) {
-							e.printStackTrace();
-						} catch (IOException e) {
-							e.printStackTrace();
-						}
-						
-						
-						break;
+	protected boolean doRemoveSDK(String sdkId) {
+		// Now actually remove it from the file...
+		DevicesType devicesType;
+		try {
+			File devicesFile = getDevicesXMLFile();
+			 
+			// if file does not exist, let exception cath it...
+			devicesType = DevicesLoader.loadDevices(devicesFile.toURL());
+			EList devices = devicesType.getDevice();
+			for (Iterator iter = devices.iterator(); iter.hasNext();) {
+				DeviceType device = (DeviceType)iter.next();
+				if (device.getId().equals(sdkId)){
+					if (!DevicesLoader.deleteDeviceEntry(device, devicesFile.toURL())){
+						return false; // write failed
 					}
+					break;
 				}
-				
-				updateCarbideSDKCache();
-				
-			} else {
-				return false;
-			}			
+			}
+			
+			return true;
+		} catch (Exception e) {
+			logError("Failed to remove SDK", e);
 		}
-		return true;
+		return false;
+		
 	}
 
 	// Read the devices.xml locaiton from the local machine registry.
@@ -400,217 +199,6 @@
 		return regPath;
 	}
 	
-	private void scanCarbideSDKCache(){
-		
-		DocumentBuilder docBuilder = null;
-		try {
-			docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-		} catch (ParserConfigurationException e) {
-			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
-			throw new RuntimeException(e);
-		}
-		
-		// NOTE: If debugging runtime workbench and you clear your configuraiton at each launch
-		// the data in the configuration location will be lost
-		Location configurationLocation = Platform.getConfigurationLocation();
-		try {
-			URL url = new URL(configurationLocation.getURL(), SDKCorePlugin.PLUGIN_ID);
-			File configFolder = new File(url.getFile());
-			if (!configFolder.exists()) {
-				configFolder.mkdirs();
-			}
-
-		    File carbideSDKCacheFile = new File(configFolder, CARBIDE_SDK_CACHE_FILE_NAME);
-		    if (!carbideSDKCacheFile.exists()){
-		    	try {
-		    	FileUtils.writeFileContents(carbideSDKCacheFile, EMPTY_STRING.toCharArray(), null);
-		    	} catch (CoreException e){
-		    		e.printStackTrace();
-		    	}
-		    }else if (carbideSDKCacheFile.length() > 0) {
-			Document lastKnownDoc = docBuilder.parse(carbideSDKCacheFile);
-			
-			NodeIterator ni = XPathAPI.selectNodeIterator(lastKnownDoc, "/sdks/sdk");
-			for (Node n = ni.nextNode(); n != null; n = ni.nextNode()) {
-				
-				// get the unique ID
-				NamedNodeMap attribs = n.getAttributes();
-				String id = attribs.getNamedItem(SDK_CACHE_ID_ATTRIB).getNodeValue();
-				
-				// get whether or not the SDK is enabled
-				String sdkEnabled = "true";
-				Node sdkEnabledItem = attribs.getNamedItem(SDK_CACHE_ENABLED_ATTRIB);
-				if (sdkEnabledItem != null)
-					sdkEnabled = sdkEnabledItem.getNodeValue();
-				
-				// get the os version
-				String osVersion = "";
-				Node osVersionItem = attribs.getNamedItem(SDK_CACHE_OS_VERSION_ATTRIB);
-				if (osVersionItem != null)
-					osVersion = osVersionItem.getNodeValue();
-				
-				// get the os branch
-				String osBranch = "";
-				Node osBranchItem = attribs.getNamedItem(SDK_CACHE_OS_BRANCH_ATTRIB);
-				if (osBranchItem != null)
-					osBranch = osBranchItem.getNodeValue();
-				
-				// get the sdk version
-				String sdkVersion = "";
-				Node sdkVersionItem = attribs.getNamedItem(SDK_CACHE_SDK_VERSION_ATTRIB);
-				if (sdkVersionItem != null)
-					sdkVersion = sdkVersionItem.getNodeValue();
-				
-				// get whether or not this SDK has been scanned
-				String wasScanned = "false";
-				Node sdkScannedItem = attribs.getNamedItem(SDK_SCANNED_FOR_PLUGINS);
-				if (sdkScannedItem != null)
-					wasScanned = sdkScannedItem.getNodeValue();
-				
-				ISymbianSDK sdk = getSDK(id, false);
-				if (sdk != null){
-					
-					if (wasScanned.equalsIgnoreCase("true")){
-						sdk.setPreviouslyScanned(true);
-					} else {
-						sdk.setPreviouslyScanned(false);
-					}
-					
-					if (sdkEnabled.equalsIgnoreCase("true")){
-						sdk.setEnabled(true);
-					} else {
-						sdk.setEnabled(false);
-					}
-					
-					if (!osVersion.equals("")){
-						if (Version.parseVersion(osVersion).getMajor() != 0){
-							sdk.setOSVersion(Version.parseVersion(osVersion));
-						}
-					}
-					
-					if (!osBranch.equals("")){
-						sdk.setOSSDKBranch(osBranch);
-					}
-					
-					if (!sdkVersion.equals("")){
-						if (Version.parseVersion(sdkVersion).getMajor() != 0){
-							sdk.setSDKVersion(Version.parseVersion(sdkVersion));
-						}
-					}
-					
-				}
-				
-			} // for
-		} 
-	} catch (TransformerException e) {
-	} catch (SAXException e) {
-	} catch (IOException e) {
-	}
-	}
-	
-	public void updateCarbideSDKCache() {
-		if (!Platform.isRunning())
-			return;
-			
-		DocumentBuilder docBuilder = null;
-		try {
-			docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-		} catch (ParserConfigurationException e) {
-			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
-			return;
-		}
-		
-		Location configurationLocation = Platform.getConfigurationLocation();
-		try {
-					
-			URL url = new URL(configurationLocation.getURL(), SDKCorePlugin.PLUGIN_ID);
-			File configFolder = new File(url.getFile());
-			if (!configFolder.exists()) {
-				configFolder.mkdirs();
-			}
-			
-			File carbideSDKCacheFile = new File(configFolder, CARBIDE_SDK_CACHE_FILE_NAME);
-		    if (!carbideSDKCacheFile.exists()){
-		    	try {
-		    	FileUtils.writeFileContents(carbideSDKCacheFile, EMPTY_STRING.toCharArray(), null);
-		    	} catch (CoreException e){
-		    		e.printStackTrace();
-		    	}
-		    }
-		    
-			Document d = docBuilder.newDocument();
-			Node sdks = d.appendChild(d.createElement("sdks"));
-				
-			synchronized(sdkList)
-			{
-				for (ISymbianSDK currSDK: sdkList) {
-					Node sdk = sdks.appendChild(d.createElement("sdk"));
-					NamedNodeMap attribs = sdk.getAttributes();
-					Node idNode = d.createAttribute(SDK_CACHE_ID_ATTRIB);
-					idNode.setNodeValue(currSDK.getUniqueId());
-					attribs.setNamedItem(idNode);
-						
-					// Hide the build config from view in the build config list?
-					Node enabledNode = d.createAttribute(SDK_CACHE_ENABLED_ATTRIB);
-					if (true == currSDK.isEnabled()) {
-						enabledNode.setNodeValue("true");
-					} else {
-						enabledNode.setNodeValue("false");
-					}
-					attribs.setNamedItem(enabledNode);
-					
-					Node wasScannedNode = d.createAttribute(SDK_SCANNED_FOR_PLUGINS);
-					if (true == currSDK.isPreviouslyScanned()) {
-						wasScannedNode.setNodeValue("true");
-					} else {
-						wasScannedNode.setNodeValue("false");
-					}
-					attribs.setNamedItem(wasScannedNode);
-					
-					Node osVerNode = d.createAttribute(SDK_CACHE_OS_VERSION_ATTRIB);
-					osVerNode.setNodeValue(currSDK.getOSVersion().toString());
-					attribs.setNamedItem(osVerNode);
-					
-					Node osBranchNode = d.createAttribute(SDK_CACHE_OS_BRANCH_ATTRIB);
-					osBranchNode.setNodeValue(currSDK.getSDKOSBranch());
-					attribs.setNamedItem(osBranchNode);
-					
-					Node sdkVerNode = d.createAttribute(SDK_CACHE_SDK_VERSION_ATTRIB);
-					sdkVerNode.setNodeValue(currSDK.getSDKVersion().toString());
-					attribs.setNamedItem(sdkVerNode);
-				}
-			}
-				DOMSource domSource = new DOMSource(d);
-				TransformerFactory transFactory = TransformerFactory.newInstance();
-				Result fileResult = new StreamResult(carbideSDKCacheFile);
-				try {
-					transFactory.newTransformer().transform(domSource, fileResult);
-				} catch (TransformerConfigurationException e) {
-					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
-				} catch (TransformerException e) {
-					ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
-				} 
-		} catch (MalformedURLException e){
-			
-		}
-	}
-	
-	public boolean getBSFScannerEnabled(){
-		return enableBSFScanner;
-	}
-	
-	public void enableBSFScanner(boolean enabled){
-		enableBSFScanner = enabled;
-	}
-	
-	public void setPlatformList(List<BuildPlat> inPlatList){
-		platList = inPlatList;
-	}
-	
-	public List<BuildPlat> getPlatformList(){
-		return platList;
-	}
-
 	public File getDevicesXMLFile() {
 		IPath devicesPath = getDevicesXMLFromRegistry();
 		
@@ -673,83 +261,6 @@
 		return gcceToolDir;
 	}
 	
-	public synchronized IRVCTToolChainInfo[] getInstalledRVCTTools() {
-		// the path wn't change inside one invocation so cache the results
-		if (rvctInfoList == null) {
-			rvctInfoList = scanForInstalledRVCTCompilers();
-		}
-		return (IRVCTToolChainInfo[]) rvctInfoList.toArray(new IRVCTToolChainInfo[rvctInfoList.size()]);
-	}
-	
-	/**
-	 * Get a list of IRVCTToolChainInfo objects for all RVCT installations detected on the PATH env var.
-	 */
-	private static List<IRVCTToolChainInfo> scanForInstalledRVCTCompilers() {
-		
-		Runtime rt=Runtime.getRuntime();
-		List<IRVCTToolChainInfo> rvctToolList = new ArrayList<IRVCTToolChainInfo>();
-		String pathStr = System.getenv("PATH");
-		String[] pathTokens = pathStr.split(";");
-		
-		for(String currTok : pathTokens) {
-			try {
-				String command = currTok;
-				command += (currTok.endsWith("\\") || currTok.endsWith("/")) ? "" : File.separator;
-				command += "armcc.exe --vsn";
-				
-				Process p = rt.exec(command);
-				
-				BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
-				
-				String overallOutput = null;
-				String stdErrLine = null;
-
-				// RVCT waits for like 4 minutes trying to find a license when the computer is
-				// not connected to the network.  in such cases, the call to br.readline doesn't
-				// return for 4 minutes which is unacceptable here.  Instead we'll poll at 1/2 second
-				// intervals for 40 seconds and see if we get a response. On the first response we break out
-				// of the loop and read the output. So in most normal circumstances it will take 1/2 to 1 seconds.
-				int maxTries = 80;
-				int numTries = 0;
-				while (numTries < maxTries) {
-					try {
-						Thread.sleep(500);
-					} catch (InterruptedException e) {
-						// ignore
-					}
-					if (br.ready()) {
-						while ((stdErrLine = br.readLine()) != null) {
-							overallOutput += stdErrLine;
-						}
-						break;
-					}
-					numTries++;
-				}
-				
-				p.destroy();
-				
-				if (overallOutput != null && overallOutput.length() > 0){
-					for (String currVersion : knownRVCTVersions) {
-						
-						if(overallOutput.contains(currVersion)) {
-							RVCTToolChainInfo rvctInfo = new RVCTToolChainInfo();
-							rvctInfo.setRvctToolBinariesDirectory(currTok);
-							rvctInfo.setRvctToolsVersion(new Version(currVersion));
-							rvctToolList.add(rvctInfo);
-							break; // tool successfully added
-						}
-					}
-				}
-			}
-			catch (IOException e) {
-				// armcc isn't in this directory, ignore....
-			}
-		}
-				
-		return rvctToolList;
-	}
-	
-
 	public void doAsynchPromptCreateDevicesXML() {
 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
 			public void run() {
@@ -829,61 +340,6 @@
 		}
 	}
 	
-    public ISymbianSDK addMissingSdk(String uid) {
-		ISymbianSDK sdk = getMissingSdk(uid);
-		if (sdk == null) {
-			sdk = SymbianMissingSDKFactory.createInstance(uid);
-			missingSdkMap.put(uid, sdk);
-		}
-    	return sdk;
-    }
-    
-    public void removeMissingSdk(String uid) {
-    	missingSdkMap.remove(uid);
-    }
-    
-    public ISymbianSDK getMissingSdk(String uid) {
-    	return missingSdkMap.get(uid);
-    }
-    
-	public List<ISymbianSDK> getMissingSDKList() {
-		List<ISymbianSDK> listCopy = new ArrayList<ISymbianSDK>();
-		synchronized(missingSdkMap) {
-			for (ISymbianSDK sdk : missingSdkMap.values()) {
-				listCopy.add(sdk);
-			}
-		}
-		return listCopy;			
-	}
-	
-	public void addInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
-		listeners.add(listener);
-	}
-	
-	public void removeInstalledSdkChangeListener(ICarbideInstalledSDKChangeListener listener) {
-		listeners.remove(listener);
-	}
-	
-	public void fireInstalledSdkChanged(SDKChangeEventType eventType) {
-		for (ICarbideInstalledSDKChangeListener l : listeners) {
-			l.installedSdkChanged(eventType);
-		}
-	}
-	
-	public void addDevicesXMLChangeListener(ICarbideDevicesXMLChangeListener listener) {
-		devicesXMLListeners.add(listener);
-	}
-	
-	public void removeDevicesXMLChangeListener(ICarbideDevicesXMLChangeListener listener) {
-		devicesXMLListeners.remove(listener);
-	}
-	
-	public void fireDevicesXMLChanged() {
-		for (ICarbideDevicesXMLChangeListener l : devicesXMLListeners) {
-			l.devicesXMLOutOfSync();
-		}
-	}
-	
 	public boolean checkDevicesXMLSynchronized(){
 		if (devicesXLMLastModified == 0){
 			return true; // no devices.xml file
@@ -954,68 +410,9 @@
 			return true;
 		}
 	}
-	
-	private void logError(String message, Throwable t) {
-		SDKCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.getPluginId(), message, t));		
+
+	@Override
+	protected boolean isEPOCRootFixed() {
+		return true;
 	}
-
-	public Version getSBSv2Version(boolean forceScan) {
-		if (sbsV2Version == null || forceScan){
-			sbsV2Version = new Version(0, 0, 0);
-			
-			Runtime rt=Runtime.getRuntime();
-			try {
-				Process p = rt.exec("sbs.bat -v");
-				
-				BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
-				String overallOutput = null;
-				String stdErrLine = null;
-				while ((stdErrLine = br.readLine()) != null) {
-					overallOutput += stdErrLine;
-				}
-				
-				if (overallOutput != null) {
-				{
-					String[] tokens = overallOutput.split(" ");
-					if (tokens.length >= 3) {
-						if (tokens[2].split("\\.").length == 3) {
-							sbsV2Version = Version.parseVersion(tokens[2]);
-						}
-					}
-						if (sbsV2Version.compareTo(MINIMUM_RAPTOR_VERSION) < 0 && sbsV2Version.getMajor() > 0) {
-
-							String incorrectRaptorVersionStr = "SBSv2 version detected: "
-									+ sbsV2Version.toString()
-									+ ". The minimum version suggested for Carbide is: "
-									+ MINIMUM_RAPTOR_VERSION.getMajor()
-									+ "."
-									+ MINIMUM_RAPTOR_VERSION.getMinor()
-									+ "."
-									+ MINIMUM_RAPTOR_VERSION.getMicro();
-
-							ResourcesPlugin.getPlugin().getLog().log(
-									new Status(IStatus.WARNING,
-											SDKCorePlugin.PLUGIN_ID,
-											IStatus.WARNING,
-											incorrectRaptorVersionStr, null));
-						}
-					
-					p.destroy();
-				}
-			}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-			
-			
-			
-		}
-		return sbsV2Version;
-	}
-
-	public Version getMinimumSupportedSBSv2Version() {
-		return MINIMUM_RAPTOR_VERSION;
-	}
-	
-	
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManagerRaptorOnly.java	Thu Dec 03 12:04:42 2009 -0600
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.carbide.cpp.internal.sdk.core.model;
+
+import java.io.File;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.carbide.cpp.internal.api.sdk.SBSv2Utils;
+import com.nokia.carbide.cpp.internal.sdk.core.gen.Devices.DefaultType;
+import com.nokia.carbide.cpp.internal.sdk.core.gen.Devices.DeviceType;
+import com.nokia.carbide.cpp.internal.sdk.core.gen.Devices.DevicesFactory;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKEnvInfoFailureException;
+import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
+
+/**
+ * This SDK manager only expects Raptor (SBSv2) to exist.
+ */
+public class SDKManagerRaptorOnly extends AbstractSDKManager {
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.sdk.core.model.AbstractSDKManager#doScanSDKs()
+	 */
+	@Override
+	protected boolean doScanSDKs() {
+		
+		String message = SBSv2Utils.scanSBSv2();
+		if (message != null) {
+			reportError(message);
+			return false;
+		}
+		
+		// TODO LINUX: real configuration
+		String epocrootStr = System.getenv("EPOCROOT");
+		if (epocrootStr == null)
+			epocrootStr = System.getProperty("user.home") + "/epocroot";
+		
+		File epocroot = new File(epocrootStr);
+		
+		if (epocroot.isDirectory()) {
+			addSymbianSDK(epocroot);
+		}
+		
+		return true;
+	}
+
+	protected void addSymbianSDK(File epocroot) {
+		// TODO LINUX: see if Raptor has a database for this stuff
+		DeviceType deviceType = DevicesFactory.eINSTANCE.createDeviceType();
+		deviceType.setDefault(DefaultType.YES_LITERAL);
+		deviceType.setEpocroot(epocroot.getAbsolutePath());
+		deviceType.setId("raptor");
+		deviceType.setName("com.nokia.s60");
+		deviceType.setAlias("Default Raptor target");
+		deviceType.setToolsroot(new File(epocroot, "epoc32/tools").getAbsolutePath());
+		deviceType.setUserdeletable("false");
+		
+		SymbianSDK sdk = new SymbianSDK(deviceType);
+		sdkList.add(sdk);
+	}
+
+	protected void reportError(final String string) {
+		if (WorkbenchUtils.isJUnitRunning())
+			return;
+		Display.getDefault().syncExec(new Runnable() {
+			public void run() {
+				MessageDialog.openWarning(WorkbenchUtils.getActiveShell(), "SBSv2 Setup Failed", string);
+			}
+		});
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.sdk.core.model.AbstractSDKManager#doRemoveSDK(java.lang.String)
+	 */
+	@Override
+	protected boolean doRemoveSDK(String sdkId) {
+		reportError("Cannot delete Raptor targets");
+		return false;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.sdk.core.ISDKManager#checkDevicesXMLSynchronized()
+	 */
+	public boolean checkDevicesXMLSynchronized() {
+		// TODO LINUX: investigate
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.sdk.core.ISDKManager#getCSLArmToolchainInstallPathAndCheckReqTools()
+	 */
+	public String getCSLArmToolchainInstallPathAndCheckReqTools()
+			throws SDKEnvInfoFailureException {
+		throw new SDKEnvInfoFailureException("CSL ARM Tools detection not yet implemented");
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.sdk.core.ISDKManager#getDevicesXMLFile()
+	 */
+	public File getDevicesXMLFile() {
+		// This is a placeholder, since this file is not used in Linux
+		return new File(System.getProperty("user.home"), "devices.xml");
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.sdk.core.ISDKManager#setDefaultSDK(com.nokia.carbide.cpp.sdk.core.ISymbianSDK)
+	 */
+	public void setDefaultSDK(ISymbianSDK sdk) {
+		// ignore
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.sdk.core.ISDKManager#updateSDK(com.nokia.carbide.cpp.sdk.core.ISymbianSDK)
+	 */
+	public void updateSDK(ISymbianSDK sdkId) {
+		updateCarbideSDKCache();
+	}
+	
+	@Override
+	protected boolean isEPOCRootFixed() {
+		return false;
+	}
+
+}
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SymbianSDK.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SymbianSDK.java	Thu Dec 03 12:04:42 2009 -0600
@@ -20,6 +20,7 @@
 import com.nokia.carbide.cpp.sdk.core.*;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.preprocessor.BasicIncludeFileLocator;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.preprocessor.MacroScanner;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.sun.org.apache.xpath.internal.XPathAPI;
 
 import org.eclipse.core.resources.ResourcesPlugin;
@@ -68,7 +69,7 @@
 	private static final String BUILD_INFO_TXT_FILE = "epoc32/data/buildinfo.txt"; //$NON-NLS-1$
 	private static final String BUILD_INFO_KEYWORD = "ManufacturerSoftwareBuild";
 	
-	private static final String WINSCW_UREL_DIR = "epoc32\\release\\winscw\\urel";
+	private static final String WINSCW_UREL_DIR = "epoc32/release/winscw/urel";
 	
 	protected DeviceType deviceEntry = null;
 	private boolean enabled = true;
@@ -350,7 +351,7 @@
 	public IPath getIncludePath() {
 		String epocRoot = getEPOCROOT();
 		if (epocRoot.length() > 0) {
-			IPath epoc32IncPath = new Path(epocRoot).append("epoc32\\include");
+			IPath epoc32IncPath = new Path(epocRoot).append("epoc32/include");
 			// try to canonicalize it so it matches actual file system case
 			try {
 				epoc32IncPath = new Path(epoc32IncPath.toFile().getCanonicalPath());
@@ -414,7 +415,7 @@
 	public IPath getReleaseRoot() {
 		String epocRoot = getEPOCROOT();
 		if (epocRoot.length() > 0) {
-			IPath epoc32RelPath = new Path(epocRoot).append("epoc32\\release");
+			IPath epoc32RelPath = new Path(epocRoot).append("epoc32/release");
 			// try to canonicalize it so it matches actual file system case
 			try {
 				epoc32RelPath = new Path(epoc32RelPath.toFile().getCanonicalPath());
@@ -443,7 +444,7 @@
 	public IPath getToolsPath() {
 		String epocRoot = getEPOCROOT();
 		if (epocRoot.length() > 0) {
-			IPath epoc32ToolsPath = new Path(epocRoot).append("epoc32\\tools");
+			IPath epoc32ToolsPath = new Path(epocRoot).append("epoc32/tools");
 			// try to canonicalize it so it matches actual file system case
 			try {
 				epoc32ToolsPath = new Path(epoc32ToolsPath.toFile().getCanonicalPath());
@@ -1102,7 +1103,7 @@
 					variantDir = matcher.group(1);
 					variantFile = matcher.group(3); 
 					File variantFullPathFile = new File(epocRoot, variantDir + File.separator + variantFile);
-					IPath variantFilePath = new Path(variantFullPathFile.getAbsolutePath());
+					IPath variantFilePath = new Path(HostOS.convertPathToUnix(variantFullPathFile.getAbsolutePath()));
 					return variantFilePath;
 				}
 			}
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/sdk/core/SDKCorePlugin.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/sdk/core/SDKCorePlugin.java	Thu Dec 03 12:04:42 2009 -0600
@@ -16,6 +16,8 @@
 import org.osgi.framework.BundleContext;
 
 import com.nokia.carbide.cpp.internal.sdk.core.model.SDKManager;
+import com.nokia.carbide.cpp.internal.sdk.core.model.SDKManagerRaptorOnly;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 
 /**
@@ -31,7 +33,7 @@
 	// The shared instance
 	private static SDKCorePlugin plugin;
 	
-	private static SDKManager sdkManager;
+	private static ISDKManager sdkManager;
 	
 	/**
 	 * The constructor
@@ -76,7 +78,10 @@
 	 */
 	public static ISDKManager getSDKManager() {
 		if (sdkManager == null) {
-			sdkManager = new SDKManager();
+			if (HostOS.IS_WIN32)
+				sdkManager = new SDKManager();
+			else
+				sdkManager = new SDKManagerRaptorOnly();
 		}
 		return sdkManager;
 	}
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Thu Dec 03 12:04:42 2009 -0600
@@ -101,7 +101,8 @@
 		GRAY = shell.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
 		
 		// check that devices.xml actually exists
-		((SDKManager) sdkMgr).checkDevicesXMLExistAndCreate();
+		if (sdkMgr instanceof SDKManager)
+			((SDKManager) sdkMgr).checkDevicesXMLExistAndCreate();
 		
 		Composite content = new Composite(parent, SWT.NONE);
 		setControl(content);
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/shared/BuildTargetsPage.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/shared/BuildTargetsPage.java	Thu Dec 03 12:04:42 2009 -0600
@@ -45,6 +45,7 @@
 import com.nokia.carbide.internal.api.templatewizard.ui.IWizardDataPage;
 import com.nokia.carbide.template.engine.ITemplate;
 import com.nokia.cpp.internal.api.utils.core.Check;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 /**
  * Wizard page used to select a list of Carbide.c++ build configurations.  Currently used
@@ -274,6 +275,11 @@
 	
 	protected void checkPathWithSDKs(IPath path) {
 		setMessage(null);
+		
+		// drives are relevant in Windows only
+		if (!HostOS.IS_WIN32)
+			return;
+		
 		for (ISymbianBuildContext context : getSelectedBuildConfigs()) {
 			Path sdkPath = new Path(context.getSDK().getEPOCROOT());
 			if (sdkPath.getDevice() != null) {
--- a/core/com.nokia.carbide.templatewizard/src/com/nokia/carbide/internal/api/templatewizard/ui/TemplateWizardPage.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.templatewizard/src/com/nokia/carbide/internal/api/templatewizard/ui/TemplateWizardPage.java	Thu Dec 03 12:04:42 2009 -0600
@@ -117,9 +117,10 @@
 			values.put(type.getId(), value);
 			
 			if (type instanceof UidFieldType) {
+				values.put(type.getId(), value.toLowerCase());
 				// least hacky way to support this without creating a language out of templates
 				values.put(type.getId() + UIDComposite.WITHOUT_0X_PREFIX, 
-						UIDComposite.getWithout0x(value));
+						UIDComposite.getWithout0x(value).toLowerCase());
 			}
 
 		}
@@ -284,7 +285,10 @@
 		
 		@Override
 		public String getValue() {
-			return UIDComposite.makeCanonicalHexString(super.getValue().trim());
+			String value = super.getValue().trim();
+			if (!UIDComposite.isValidHexString(value))
+				return value;
+			return UIDComposite.makeCanonicalHexString(value);
 		}
 		
 		@Override
--- a/core/com.nokia.carbide.templatewizard/src/com/nokia/carbide/internal/api/templatewizard/ui/UIDComposite.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.carbide.templatewizard/src/com/nokia/carbide/internal/api/templatewizard/ui/UIDComposite.java	Thu Dec 03 12:04:42 2009 -0600
@@ -163,7 +163,9 @@
 	}
 	
 	public static String getWithout0x(String with0x) {
-		Check.checkContract(with0x.startsWith(HEX_PREFIX));
+		// may not be valid...
+		if (!with0x.startsWith(HEX_PREFIX))
+			return with0x;
 		return with0x.substring(HEX_PREFIX.length());
 	}
 
--- a/core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/FileUtils.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/FileUtils.java	Thu Dec 03 12:04:42 2009 -0600
@@ -847,7 +847,7 @@
 		if (path == null)
 			return null;
 		
-		if (Platform.getOS().equals(Platform.OS_WIN32)) {
+		if (HostOS.IS_WIN32) {
 			return new Path(path.toOSString().toLowerCase());
 		}
 		
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/HostOS.java	Thu Dec 03 12:04:42 2009 -0600
@@ -0,0 +1,161 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.cpp.internal.api.utils.core;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * Utilities used for portability between hosts.
+ */
+public class HostOS {
+	/** Is the host Windows? */
+	public static boolean IS_WIN32 = File.separatorChar == '\\';
+	/** Is the host some Unix variant? */
+	public static boolean IS_UNIX = File.separatorChar == '/';
+	
+	/** The name of the PATH variable in the environment.  Capitalized differently per OS. */
+	public static String PATH_VARIABLE_NAME = IS_WIN32 ? "Path" : "PATH";
+	
+	/**
+	 * Convert a variable constructed blindly for a Win32 environment into
+	 * Unix-like syntax.  This is typically used for PATH or lists
+	 * of paths where ';' is the entry separator and '\' is the 
+	 * path component separator.
+	 * <p>
+	 * NOTE: we assume that the entries in the
+	 * path list are already legal Unix paths, but just with the
+	 * wrong slash.
+	 * @param env
+	 * @return converted string
+	 */
+	public static String convertPathListToUnix(String env) {
+		if (env == null) return null;
+		env = env.replaceAll(";", ":");  // entry separators
+		env = env.replaceAll("\\\\", "/");  // path separators
+		return env;
+	}
+
+	/**
+	 * Convert a path constructed blindly for a Win32 environment into
+	 * Unix-like syntax.  <p>
+	 * NOTE: we assume that the path is already a legal Unix path, 
+	 * but just with the wrong slash.
+	 * @param file
+	 * @return converted string
+	 */
+	public static String convertPathToUnix(String file) {
+		if (file == null) return null;
+		// handle Windows slashes and canonicalize
+		file = file.replaceAll("\\\\", "/");
+		return file;
+	}
+	
+
+	/**
+	 * Convert a path which may be in Windows or Unix format to Windows format.
+	 * NOTE: we assume that the path is already a legal path, 
+	 * but just with the wrong slash.
+	 * @param file
+	 * @return converted string
+	 */
+	public static String convertPathToWindows(String file) {
+		if (file == null) return null;
+		file = file.replaceAll("/", "\\\\");
+		return file;
+	}
+	
+	/**
+	 * Convert a path which may be in Windows or Unix format to Windows format.
+	 * NOTE: we assume that the path is already a legal path, 
+	 * but just with the wrong slash.
+	 * @param file
+	 * @return converted string
+	 */
+	public static String convertPathToWindows(IPath path) {
+		return convertPathToWindows(path.toPortableString());
+	}
+
+	/**
+	 * Ensure that the executable name mentioned is canonical for the machine.
+	 * This only affects Windows, currently, ensuring that an ".exe" is attached.
+	 * @param executablePath
+	 * @return updated path
+	 */
+	public static String canonicalizeExecutableName(String executable) {
+		if (IS_WIN32) {
+			IPath executablePath = new Path(executable);
+			String ext = executablePath.getFileExtension();
+			if (ext == null) {
+				executable += ".exe";
+			}
+		}
+		return executable;
+	}
+
+	/**
+	 * Get the PATH entries from the given path environment value or the
+	 * system environment.
+	 * @param pathValue the expected PATH/Path value, or <code>null</code> for the system value
+	 * @return array of IPath, never <code>null</code>
+	 */
+	public static IPath[] getPathEntries(String pathValue) {
+		String pathVar = pathValue != null ? pathValue : System.getenv(PATH_VARIABLE_NAME);
+		
+		if (pathVar == null)
+			pathVar = "";
+		
+		String pathSeparator = System.getProperty("path.separator");
+		String[] pathEntries = pathVar.split(pathSeparator);
+		IPath[] paths = new IPath[pathEntries.length];
+		for (int i = 0; i < pathEntries.length; i++) {
+			paths[i] = new Path(pathEntries[i]);
+		}
+		return paths;
+	}
+	
+	/**
+	 * Scan the PATH variable and see if the given binary is visible on
+	 * the PATH that will be used at runtime (with the default environment and overrides).
+	 * @param pathValue the expected Path 
+	 * @param program
+	 * @return IPath if program is on PATH, else <code>null</code>
+	 */
+	public static IPath findProgramOnPath(String program, String pathValue) {
+		
+		// be sure proper path/extension are present
+		program = canonicalizeExecutableName(program);
+		
+		IPath path = null;
+		
+		IPath[] pathEntries = getPathEntries(pathValue);
+		for (IPath pathEntry : pathEntries) {
+			IPath testPath = pathEntry.append(program);
+			if (testPath.toFile().exists()) {
+				path = testPath;
+				break;
+			}
+		}
+		
+		return path;
+	}
+	
+	
+}
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/BaseTest.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/BaseTest.java	Thu Dec 03 12:04:42 2009 -0600
@@ -39,6 +39,7 @@
 import com.nokia.carbide.internal.cpp.epoc.engine.preprocessor.ASTPreprocessor;
 import com.nokia.carbide.internal.cpp.epoc.engine.preprocessor.IConditionalBlock;
 import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.IMessage;
 import com.nokia.cpp.internal.api.utils.core.TextUtils;
 
@@ -153,6 +154,18 @@
 	private HashMap<String, String> refMap;
 	protected IPath modelPath;
 	
+	protected String getTokenAbsolutePath() {
+		return HostOS.IS_WIN32 
+			 ? "c:\\tests\\" : "/tmp/";
+	}
+	
+	protected String toDosPath(IPath path) {
+		return path.toPortableString().replaceAll("/", "\\\\");
+	}
+	protected String toDosPath(String path) {
+		return path.replaceAll("/", "\\\\");
+	}
+	
 	/* (non-Javadoc)
 	 * @see junit.framework.TestCase#setUp()
 	 */
@@ -160,7 +173,7 @@
 	protected void setUp() throws Exception {
 		super.setUp();
 		if (projectPath == null)
-			projectPath = new Path("c:/tests/project");
+			projectPath = new Path(getTokenAbsolutePath()).append("project");
 		parserConfig = new ParserConfigurationBase(projectPath) {
 
 			@Override
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/ParserConfigurationBase.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/ParserConfigurationBase.java	Thu Dec 03 12:04:42 2009 -0600
@@ -26,6 +26,7 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.IASTTranslationUnit;
 import com.nokia.carbide.internal.cpp.epoc.engine.parser.IDocumentParser;
 import com.nokia.carbide.internal.cpp.epoc.engine.parser.ParserFactory;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
@@ -105,6 +106,10 @@
 		fileLocator = new IIncludeFileLocator() {
 		
 			public File findIncludeFile(String file, boolean isUser, File currentDir) {
+				if (HostOS.IS_UNIX) {
+					file = HostOS.convertPathToUnix(file);
+				}
+				
 				if (fs.containsKey(file))
 					return new File(file);
 				
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/conversion/TestAifdefFileConversion.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/conversion/TestAifdefFileConversion.java	Thu Dec 03 12:04:42 2009 -0600
@@ -32,11 +32,13 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.image.IPathResolver;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.image.LegacyImageFileConverterFactory;
 import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 
 public class TestAifdefFileConversion extends BaseTest {
 
-	private static final String BAD_PROJECT_ROOT = "c:/workspace/CarbideTest/FormTime/";
+	private static final String BAD_PROJECT_ROOT = 
+		HostOS.IS_WIN32 ? "c:/workspace/CarbideTest/FormTime/" : "/home/me/workspace/CarbideTest/FormTime/";
 	private File tmpdir;
 	private File tmpMbmdef;
 	private IPathResolver resolver;
@@ -88,7 +90,7 @@
 	
 	
 	static final String AIFDEF_1 =
-		BAD_PROJECT_ROOT + "|aif/formtimeaif.rss|c4,1|aif/context_pane_icon.bmp|aif/context_pane_icon_mask.bmp|aif/list_icon.bmp|aif/list_icon_mask.bmp\r\n" + 
+		BAD_PROJECT_ROOT + "|aif/FormTimeAif.rss|c4,1|aif/context_pane_icon.bmp|aif/context_pane_icon_mask.bmp|aif/list_icon.bmp|aif/list_icon_mask.bmp\r\n" + 
 		"";
 	
 	public void testAifdef1() throws CoreException {
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBSFView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBSFView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -43,7 +43,7 @@
 	@Override
 	protected void setUp() throws Exception {
 		super.setUp();
-		this.path = new Path("c:\\symbian\\9.5\\epoc32\\tools\\Test.bsf");
+		this.path = new Path("c:/symbian/9.5/epoc32/tools/Test.bsf");
 	
 		config = new IViewConfiguration() {
 	
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -22,8 +22,11 @@
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.DefineFactory;
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.IDefine;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.IASTProblemNode;
+import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.IMessage;
 
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 
 import java.util.ArrayList;
@@ -446,13 +449,13 @@
 		
 		exp = view.createExport();
 		exp.setSourcePath(new Path("gfx/myfile.mbm"));
-		exp.setTargetPath(new Path("\\sys\\resources\\MyApp\\myfile.mbm"));
-		assertEquals(new Path("\\sys\\resources\\MyApp\\myfile.mbm"), exp.getTargetPath());
+		exp.setTargetPath(new Path("/sys/resources/MyApp/myfile.mbm"));
+		assertEquals(new Path("/sys/resources/MyApp/myfile.mbm"), exp.getTargetPath());
 		view.getExports().add(exp);
 
 		exp = view.createExport();
 		exp.setSourcePath(new Path("inc/header2.h"));
-		exp.setTargetPath(new Path("\\epoc32\\include\\header2.h"));
+		exp.setTargetPath(new Path("/epoc32/include/header2.h"));
 		view.getExports().add(exp);
 
 		exp = view.createExport();
@@ -509,7 +512,7 @@
 		IBldInfView view = getView(config);
 		assertNotNull(view);
 	
-		view.getExports().get(1).setTargetPath(new Path("\\sys\\resources\\MyApp\\myfile.mbm"));
+		view.getExports().get(1).setTargetPath(new Path("/sys/resources/MyApp/myfile.mbm"));
 		
 		commitTest(view,
 				"PRJ_EXPORTS\n"+
@@ -565,11 +568,19 @@
 		assertEquals(2, view.getMessages().length);
 	}
 	
+	private static IPath insideSDKPath;
+	static {
+		if (HostOS.IS_WIN32) {
+			insideSDKPath = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello\\group\\bld.inf");
+		} else {
+			insideSDKPath = new Path("/home/user/symbian/9.1/S60_3rd/S60Ex/Hello/group/bld.inf");
+		}
+	}
 	public void testRootProject() {
 		// make sure we handle project root correctly when it's the root directory
 		for (int i = 0; i < 2; i++){
 			parserConfig.projectPath = i == 0 ? new Path("c:\\") : new Path("c:");
-			this.path = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello\\group\\bld.inf");
+			this.path = insideSDKPath;
 			makeModel("PRJ_MMPFILES\n"+
 					"test.mmp\n");
 			
@@ -581,16 +592,24 @@
 
 	private void _testRootProject(IBldInfData bldInfData) {
 		IMMPReference mmp = bldInfData.getAllMMPReferences()[0];
-		// important to be relative
-		assertEquals(new Path("symbian/9.1/S60_3rd/S60Ex/Hello/group/test.mmp"), mmp.getPath());
+		// important to be relative and with no drive
+		if (HostOS.IS_WIN32)
+			assertEquals(insideSDKPath.makeRelative().setDevice(null).removeLastSegments(1).append("test.mmp"), mmp.getPath());
+		else
+			assertEquals(insideSDKPath.removeLastSegments(1).append("test.mmp"), mmp.getPath());
 	}
 	
 	/**
 	 * The base directory changes as files are #included
 	 *
 	 */
+	private static IPath basePath;
 	public void testBaseDirectory() {
-		parserConfig.getFilesystem().put(new Path("c:/test/bld.inf").toOSString(), 
+		if (HostOS.IS_WIN32)
+			basePath = new Path("c:/test/");
+		else
+			basePath = new Path("/tmp/test/");
+		parserConfig.getFilesystem().put(basePath.append("bld.inf").toOSString(), 
 				"PRJ_MMPFILES\n"+
 				"base.mmp\n"+
 				"gnumakefile sub\\base.mk\n"+
@@ -607,7 +626,7 @@
 		makeModel(
 				"PRJ_MMPFILES\n"+
 				"first.mmp\n"+
-				"#include \"c:\\test\\bld.inf\"\n"+
+				"#include \"" + basePath.toOSString() + "bld.inf\"\n"+
 				"#include \"../utils/bld.inf\"\n"+
 				"PRJ_MMPFILES\n"+
 				"last.mmp\n" +
@@ -626,8 +645,8 @@
 		assertEquals(new Path("group/first.mmp"), bldInfData.getMakMakeReferences().get(0).getPath());
 		
 		// note: should not be relative path when outside the project
-		assertEquals(new Path("c:/test/base.mmp"), bldInfData.getMakMakeReferences().get(1).getPath());
-		assertEquals(new Path("c:/test/sub/base.mk"), bldInfData.getMakMakeReferences().get(2).getPath());
+		assertEquals(basePath.append("base.mmp"), bldInfData.getMakMakeReferences().get(1).getPath());
+		assertEquals(basePath.append("sub/base.mk"), bldInfData.getMakMakeReferences().get(2).getPath());
 		
 		assertEquals(new Path("utils/utils.mmp"), bldInfData.getMakMakeReferences().get(3).getPath());
 		assertEquals(new Path("utils.mk"), bldInfData.getMakMakeReferences().get(4).getPath());
@@ -635,7 +654,7 @@
 		assertEquals(new Path("group/last.mmp"), bldInfData.getMakMakeReferences().get(5).getPath());
 
 		assertEquals(3, bldInfData.getExports().size());
-		assertEquals(new Path("c:/test/base.txt"), bldInfData.getExports().get(0).getSourcePath());
+		assertEquals(basePath.append("base.txt"), bldInfData.getExports().get(0).getSourcePath());
 		assertEquals(new Path("utils/utils.txt"), bldInfData.getExports().get(1).getSourcePath());
 		assertEquals(new Path("group/last.txt"), bldInfData.getExports().get(2).getSourcePath());
 	}
@@ -978,7 +997,7 @@
 				"//  End of File  \r\n"; 
 				
 		Map<String, String> originalFiles = new HashMap<String, String>();
-		originalFiles.put("..\\Speeddial\\group\\bld.inf", spdiaText);
+		originalFiles.put(new Path("../Speeddial/group/bld.inf").toOSString(), spdiaText);
 		// this fails
 		originalFiles.put("platform_paths.hrh", "\n"+"#ifndef MACRO\n"+"#define MACRO\n"+"\n"+"#endif\n"+"\n");
 		// this passes
@@ -1270,7 +1289,7 @@
 			"*  Description : \r\n" + 
 			"*  Version     : \r\n" + 
 			"*\r\n" + 
-			"*  Copyright © 2006 Nokia. All rights reserved.\r\n" + 
+			"*  Copyright (c) 2006 Nokia. All rights reserved.\r\n" + 
 			"*  This material, including documentation and any related\r\n" + 
 			"*  computer programs, is protected by copyright controlled by\r\n" + 
 			"*  Nokia Corporation. All rights are reserved. Copying,\r\n" + 
@@ -1329,7 +1348,7 @@
 			"*    whole MusicPlayer application including all related libraries.\r\n" + 
 			"*  Version     : \r\n" + 
 			"*\r\n" + 
-			"*  Copyright © 2002-2006 Nokia Corporation.\r\n" + 
+			"*  Copyright (c) 2002-2006 Nokia Corporation.\r\n" + 
 			"*  This material, including documentation and any related \r\n" + 
 			"*  computer programs, is protected by copyright controlled by \r\n" + 
 			"*  Nokia Corporation. All rights are reserved. Copying, \r\n" + 
@@ -1430,7 +1449,7 @@
 			"*                that make up the MusicShopEmbed, MusicShopApp and MusicShopLib\r\n" + 
 			"*  Version	: %version: da1mmcf#15 %\r\n" + 
 			"*\r\n" + 
-			"*  Copyright © 2006 Nokia. All rights reserved.\r\n" + 
+			"*  Copyright (c) 2006 Nokia. All rights reserved.\r\n" + 
 			"*  This material, including documentation and any related\r\n" + 
 			"*  computer programs, is protected by copyright controlled by\r\n" + 
 			"*  Nokia Corporation. All rights are reserved. Copying,\r\n" + 
@@ -1477,7 +1496,7 @@
 			"*    all MusicVisualization projects including plugins.\r\n" + 
 			"*  Version     : \r\n" + 
 			"*\r\n" + 
-			"*  Copyright © 2005 Nokia Corporation.\r\n" + 
+			"*  Copyright (c) 2005 Nokia Corporation.\r\n" + 
 			"*  This material, including documentation and any related \r\n" + 
 			"*  computer programs, is protected by copyright controlled by \r\n" + 
 			"*  Nokia Corporation. All rights are reserved. Copying, \r\n" + 
@@ -1508,9 +1527,12 @@
 			"\r\n" + 
 			"// End of File\r\n" ; 
 			
-		parserConfig.getFilesystem().put("..\\MusicPlayer\\group\\bld.inf", musicPlayerBldInf);
-		parserConfig.getFilesystem().put("..\\MusicShop\\group\\bld.inf", musicShopBldInf);
-		parserConfig.getFilesystem().put("..\\MusicVisualization\\group\\bld.inf", musicVisualizationBldInf);
+		String musicPlayerBldInfPath = FileUtils.createPossiblyRelativePath("../MusicPlayer/group/bld.inf").toOSString();
+		parserConfig.getFilesystem().put(musicPlayerBldInfPath, musicPlayerBldInf);
+		String musicShopBldInfPath = FileUtils.createPossiblyRelativePath("../MusicShop/group/bld.inf").toOSString();
+		parserConfig.getFilesystem().put(musicShopBldInfPath, musicShopBldInf);
+		String musicVisBldInfPath = FileUtils.createPossiblyRelativePath("../MusicVisualization/group/bld.inf").toOSString();
+		parserConfig.getFilesystem().put(musicVisBldInfPath, musicVisualizationBldInf);
 			
 		makeModel(origFile);
 		
@@ -1518,13 +1540,13 @@
 		assertNotNull(view);
 		
 		IMMPReference ref = view.createMMPReference();
-		ref.setPath(new Path("group\\FMRadio.mmp"));
+		ref.setPath(new Path("group/FMRadio.mmp"));
 		view.getMakMakeReferences().add(ref);
 		
+		assertEquals(parserConfig.getFilesystem().get(musicPlayerBldInfPath), musicPlayerBldInf);
+		assertEquals(parserConfig.getFilesystem().get(musicShopBldInfPath), musicShopBldInf);
+		assertEquals(parserConfig.getFilesystem().get(musicVisBldInfPath), musicVisualizationBldInf);
 		commitTest(view, updatedFile);
-		assertEquals(parserConfig.getFilesystem().get("..\\MusicPlayer\\group\\bld.inf"), musicPlayerBldInf);
-		assertEquals(parserConfig.getFilesystem().get("..\\MusicShop\\group\\bld.inf"), musicShopBldInf);
-		assertEquals(parserConfig.getFilesystem().get("..\\MusicVisualization\\group\\bld.inf"), musicVisualizationBldInf);
  
 	}
 	
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView4.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestBldInfView4.java	Thu Dec 03 12:04:42 2009 -0600
@@ -244,7 +244,7 @@
 		
 		assertEquals(new Path("base/config"), ext.getTemplatePath());
 		assertEquals("armcc", ext.getToolName());
-		assertEquals(new Path("zap_ma_ma\\"), ext.getTargetPath());
+		assertEquals(new Path("zap_ma_ma/"), ext.getTargetPath());
 		assertNotNull(ext.getSources());
 		assertEquals(2, ext.getSources().size());
 		assertEquals(new Path("src/file1.cpp"), ext.getSources().get(0));
@@ -725,9 +725,9 @@
 		view = getView(config);
 		assertEquals(1, view.getMakMakeReferences().size());
 		IMakMakeReference mak = view.getMakMakeReferences().get(0);
-		assertEquals(new Path("\\test\\drivers\\cpa_log_kernel.mmp"), mak.getPath());
+		assertEquals(new Path("/test/drivers/cpa_log_kernel.mmp"), mak.getPath());
 		
-		mak.setPath(new Path("\\test\\drivers\\kernel.mmp"));
+		mak.setPath(new Path("/test/drivers/kernel.mmp"));
 		commitTest(view, text2);
 	}
 	public void testBug3696() {
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestImageMakefileView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestImageMakefileView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -26,6 +26,7 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.preprocessor.BasicIncludeFileLocator;
 import com.nokia.carbide.internal.cpp.epoc.engine.model.StandaloneModelProvider;
 import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 import org.eclipse.cdt.make.core.makefile.IDirective;
 import org.eclipse.cdt.make.core.makefile.gnu.IInclude;
@@ -99,11 +100,22 @@
 	}
 	
 	protected void makeModel(String text) {
+		text = convertForOS(text);
 		IDocument document = DocumentFactory.createDocument(text);
 		model = new ImageMakefileModelFactory().createModel(path, document);
 
 		model.parse();
 	}
+
+	private String convertForOS(String text) {
+		// TODO: tests should work with both slash directions on both OSes
+		if (HostOS.IS_UNIX) {
+			text = text.replaceAll("\\\\(?!\r|\n)", "/");
+			text = text.replaceAll("(?<=\\s|^)/([A-Z])", "-$1"); 
+			text = text.replaceAll("(?<=\\s|^)/(c?(\\d|,)+)", "-$1");
+		}
+		return text;
+	}
 	
 	protected IImageMakefileView getView(IImageMakefileViewConfiguration config) {
 		IImageMakefileView view = (IImageMakefileView) model.createView(config);
@@ -112,9 +124,26 @@
 	}
 	
 	protected void commitTest(IImageMakefileView view, String refText) {
+		refText = convertForOS(refText);
 		commitTest(model, view, refText);
 	}
 	
+	private static IPath stockRootedProjectPath;
+	private static IPath stockRootedImgPath;
+	private static IPath stockRootedSvgPath;
+	
+	static {
+		if (HostOS.IS_WIN32) {
+			stockRootedProjectPath = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello");
+			stockRootedImgPath = new Path("c:\\imgs\\");
+			stockRootedSvgPath = new Path("c:\\svgs\\");
+		} else {
+			stockRootedProjectPath = new Path("/home/me/Hello");
+			stockRootedImgPath = new Path("/tmp/imgs/");
+			stockRootedSvgPath = new Path("/tmp/svgs/");
+		}
+	}
+	
 	final String TEST_1 =
 		"# ============================================================================\r\n" + 
 		"#  Name     : Icons_aif_scalable_dc.mk\r\n" + 
@@ -570,7 +599,7 @@
 		"ICONDIR=..\\aif\r\n" + 
 		"\r\n" + 
 		"$(ICONTARGETFILENAME): $(ICONDIR)\\icon1.svg $(ICONDIR)\\icon2.svg\r\n" + 
-		"	mifconv $< /E /Bbmconv.exe /h$(HEADERDIR)/Birthdays_aif.mbg /c16 $@\r\n" + 
+		"	mifconv $< /E /Bbmconv.exe /H$(HEADERDIR)/Birthdays_aif.mbg /c16 $@\r\n" + 
 		"	mifconv extra.mif /c8,8 /Fbitmaps.txt\r\n" + 
 		"FREEZE : do_nothing\r\n" + 
 		"\r\n" + 
@@ -583,13 +612,13 @@
 		"\r\n"; 
 		
 	final String TEST_2_inc =
-		"\t../pix/bitmap1.bmp\t\nbitmap2.bmp\\\n/1,1\nc:\\test\\dot.bmp\t\n";
+		"\t../pix/bitmap1.bmp\t\nbitmap2.bmp\\\n/1,1\n"+stockRootedImgPath.append("dot.bmp")+"\t\n";
 	
 	public void testImageContainerParsing2()throws Exception {
 		File incFile = new File(projectPath.toFile(), "group/bitmaps.txt");
 		incFile.getParentFile().mkdir();
 		incFile.delete();
-		FileUtils.writeFileContents(incFile, TEST_2_inc.toCharArray(), null);
+		FileUtils.writeFileContents(incFile, convertForOS(TEST_2_inc).toCharArray(), null);
 		
 		makeModel(TEST_2);
 		IImageMakefileView view = (IImageMakefileView) model.createView(viewConfig);
@@ -608,7 +637,7 @@
 		assertEquals(EGeneratedHeaderFlags.Header, c.getHeaderFlags());
 		// default value not represented
 		assertNull(c.getGeneratedHeaderFilePath());
-		assertEquals(new Path("epoc32\\include\\Birthdays_aif.mbg"), c.getDefaultGeneratedHeaderFilePath());
+		assertEquals(new Path("epoc32/include/Birthdays_aif.mbg"), c.getDefaultGeneratedHeaderFilePath());
 		assertEquals("Birthdays_aif.mif", c.getTargetFile());
 		assertEquals(new Path("resource/apps"),
 				c.getTargetPath());
@@ -663,12 +692,12 @@
 		assertFalse(b.isColor());
 		assertEquals(1, b.getDepth());
 		assertEquals(1, b.getMaskDepth());
-		assertEquals(new Path("c:/test/dot.bmp"), b.getPath());
+		assertEquals(stockRootedImgPath.append("dot.bmp"), b.getPath());
 		assertNull(b.getMaskPath());
-		assertEquals(new Path("c:/test/dot_mask.bmp"), b.getDefaultMaskPath());
+		assertEquals(stockRootedImgPath.append("dot_mask.bmp"), b.getDefaultMaskPath());
 	}
 
-	// alternate style uses \\epoc32 directly
+	// alternate style uses /epoc32 directly
  	final String TEST_3 = 
  		"# ============================================================================\r\n" + 
  			"#  Name     : Icons_aif_scalable_dc.mk\r\n" + 
@@ -712,7 +741,7 @@
  			"CLEANLIB : do_nothing\r\n" + 
  			"\r\n" + 
  			"RESOURCE :	\r\n" + 
- 			"	mifconv $(ICONTARGETFILENAME) /h$(HEADERFILENAME) \\\r\n" + 
+ 			"	mifconv $(ICONTARGETFILENAME) /H$(HEADERFILENAME) \\\r\n" + 
  			"		/c32 $(ICONDIR)\\qgn_menu_Birthdays.svg\r\n" + 
  			"		\r\n" + 
  			"FREEZE : do_nothing\r\n" + 
@@ -742,7 +771,7 @@
 		///////
 		IMultiImageSource c = mis.get(0);
 		assertEquals(EGeneratedHeaderFlags.Header, c.getHeaderFlags());
-		assertEquals(new Path("\\epoc32\\include\\Birthdays_aif.mbg"), c.getGeneratedHeaderFilePath());
+		assertEquals(new Path("/epoc32/include/Birthdays_aif.mbg"), c.getGeneratedHeaderFilePath());
 		assertEquals("Birthdays_aif.mif", c.getTargetFile());
 		assertEquals(new Path("/epoc32/data/z/resource/apps"),
 				c.getTargetPath());
@@ -760,7 +789,7 @@
 	// no extension --> svg
  	final String TEST_4 = 
  			"ifeq (WINS,$(findstring WINS, $(PLATFORM)))\r\n" + 
- 			"ZDIR=\\epoc32\\release\\$(PLATFORM)\\$(CFG)\\Z\r\n" + 
+ 			"ZDIR=/epoc32\\release\\$(PLATFORM)\\$(CFG)\\Z\r\n" + 
  			"else\r\n" + 
  			"ZDIR=\\epoc32\\data\\z\r\n" + 
  			"endif\r\n" + 
@@ -773,7 +802,7 @@
  			"\r\n" + 
  			"ICONDIR=..\\gfx\r\n" + 
  			"RESOURCE :	\r\n" + 
- 			"	mifconv $(ICONTARGETFILENAME) /h$(HEADERFILENAME) \\\r\n" + 
+ 			"	mifconv $(ICONTARGETFILENAME) /H$(HEADERFILENAME) \\\r\n" + 
  			"		/c32 $(ICONDIR)\\qgn_menu_Birthdays\r\n" + 
  			"		\r\n" + 
  			""; 
@@ -868,7 +897,7 @@
 		
 		IMultiImageSource mis = view.createMultiImageSource();
 		mis.setHeaderFlags(EGeneratedHeaderFlags.Header);
-		mis.setTargetPath(new Path("epoc32\\release\\winscw\\udeb\\sys\\bin"));
+		mis.setTargetPath(new Path("epoc32/release/winscw/udeb/sys/bin"));
 		mis.setTargetFile("miffile.mif");
 		
 		view.getMultiImageSources().add(mis);
@@ -900,7 +929,7 @@
 		assertEquals(0, view.getMultiImageSources().size());
 		
 		IMultiImageSource mis = view.createMultiImageSource();
-		mis.setTargetPath(new Path("epoc32\\release\\winscw\\udeb\\sys\\bin"));
+		mis.setTargetPath(new Path("epoc32/release/winscw/udeb/sys/bin"));
 		mis.setTargetFile("miffile.mif");
 		
 		view.getMultiImageSources().add(mis);
@@ -929,8 +958,11 @@
 	public void testRootProject() {
 		// make sure we handle project root correctly when it's the root directory
 		for (int i = 0; i < 2; i++){
-			parserConfig.projectPath = i == 0 ? new Path("c:\\") : new Path("c:");
-			this.path = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello\\group\\Icons.mk");
+			if (HostOS.IS_WIN32)
+				parserConfig.projectPath = i == 0 ? new Path("c:\\") : new Path("c:");
+			else
+				parserConfig.projectPath = new Path("/");
+			this.path = stockRootedProjectPath.append("/group/Icons.mk");
 			makeModel("RESOURCE:\n"+
 					"\tmifconv hello.mif /c8,8 ../gfx/file.svg\n");
 			
@@ -943,26 +975,33 @@
 	private void _testRootProject(IImageMakefileData imageMakefileData) {
 		IImageSource source = imageMakefileData.getMultiImageSources().get(0).getSources().get(0);
 		// important to be relative
-		assertEquals(new Path("symbian/9.1/S60_3rd/S60Ex/Hello/gfx/file.svg"), source.getPath());
+		IPath relBase;
+		relBase = stockRootedProjectPath.makeRelative().setDevice(null);
+		assertEquals(relBase.append("/gfx/file.svg"), source.getPath());
 	}
 	
 	public void testMifconvBugs() {
 		makeModel("RESOURCE:\n"+
-		"\tmifconv hello.mif /c8,8 c:\\imgs\\foo.bmp /c32 c:\\svgs\\foo.svg\n");
+		"\tmifconv hello.mif /c8,8 "+stockRootedImgPath.append("foo.bmp").toOSString()
+		+" /c32 "+stockRootedSvgPath.append("foo.svg") + "\n");
 		IImageMakefileView view =model.createView(this.viewConfig);
 
 		IImageSource source = view.getMultiImageSources().get(0).getSources().get(0);
 		// BMPs can have drive letter on input...
-		assertEquals(new Path("c:/imgs/foo.bmp"), source.getPath());
+		assertEquals(stockRootedImgPath.append("foo.bmp"), source.getPath());
 		source.setMaskDepth(1);
 
 		source = view.getMultiImageSources().get(0).getSources().get(1);
 		// SVGs can have drive letter on input...
-		assertEquals(new Path("c:/svgs/foo.svg"), source.getPath());
+		assertEquals(stockRootedSvgPath.append("foo.svg"), source.getPath());
 
 		// drop drive letters on output for bmps
-		commitTest(view, "RESOURCE:\n"+
-		"\tmifconv hello.mif \\\n\t/c8,1 \\imgs\\foo.bmp \\\n\t/c32 c:\\svgs\\foo.svg\n");
+		IPath outBmpPath = stockRootedImgPath.append("foo.bmp").setDevice(null);
+		IPath outSvgPath = stockRootedSvgPath.append("foo.svg");
+		String refText = "RESOURCE:\n"+
+		"\tmifconv hello.mif \\\n\t/c8,1 "+HostOS.convertPathToWindows(outBmpPath) + " " 
+		+ "\\\n\t/c32 " + HostOS.convertPathToWindows(outSvgPath) + "\n";
+		commitTest(view, refText);
 		
 		
 	}
@@ -1260,7 +1299,7 @@
 		File incFile = new File(projectPath.toFile(), "group/bitmaps.txt");
 		incFile.getParentFile().mkdir();
 		incFile.delete();
-		FileUtils.writeFileContents(incFile, bitmapFile.toCharArray(), null);
+		FileUtils.writeFileContents(incFile, convertForOS(bitmapFile).toCharArray(), null);
 
 		makeModel("target:\n"+
 				"\tmifconv foo.mif /X /GOO /B /Smyencode.exe /H\\noob.h /Fbitmaps.txt");
@@ -1323,12 +1362,12 @@
 		File incFile = new File(projectPath.toFile(), "inc/Icons_generic.mk");
 		incFile.getParentFile().mkdir();
 		incFile.delete();
-		FileUtils.writeFileContents(incFile, incl.toCharArray(), null);
+		FileUtils.writeFileContents(incFile, convertForOS(incl).toCharArray(), null);
 		
 		File normFile = new File(projectPath.toFile(), "group/Icons_scalable.mk");
 		normFile.getParentFile().mkdir();
 		normFile.delete();
-		FileUtils.writeFileContents(normFile, text.toCharArray(), null);
+		FileUtils.writeFileContents(normFile, convertForOS(text).toCharArray(), null);
 
 		parserConfig.fileLocator = new BasicIncludeFileLocator(
 				new File[] { projectPath.append("inc").toFile() },
@@ -1362,12 +1401,12 @@
 		File incFile = new File(projectPath.toFile(), "inc/Icons_generic.mk");
 		incFile.getParentFile().mkdir();
 		incFile.delete();
-		FileUtils.writeFileContents(incFile, incl.toCharArray(), null);
+		FileUtils.writeFileContents(incFile, convertForOS(incl).toCharArray(), null);
 		
 		File normFile = new File(projectPath.toFile(), "group/Icons_scalable.mk");
 		normFile.getParentFile().mkdir();
 		normFile.delete();
-		FileUtils.writeFileContents(normFile, text.toCharArray(), null);
+		FileUtils.writeFileContents(normFile, convertForOS(text).toCharArray(), null);
 
 		parserConfig.fileLocator = new BasicIncludeFileLocator(
 				new File[] { projectPath.append("inc").toFile() },
@@ -1417,7 +1456,7 @@
 		File normFile = new File(projectPath.toFile(), "group/Icons_scalable.mk");
 		normFile.getParentFile().mkdir();
 		normFile.delete();
-		FileUtils.writeFileContents(normFile, text.toCharArray(), null);
+		FileUtils.writeFileContents(normFile, convertForOS(text).toCharArray(), null);
 
 		parserConfig.fileLocator = new BasicIncludeFileLocator(
 				new File[] { projectPath.append("inc").toFile() },
@@ -1450,7 +1489,7 @@
 		File incFile = new File(projectPath.toFile(), "inc/Icons_generic.mk");
 		incFile.getParentFile().mkdir();
 		incFile.delete();
-		FileUtils.writeFileContents(incFile, incl.toCharArray(), null);
+		FileUtils.writeFileContents(incFile, convertForOS(incl).toCharArray(), null);
 		
 		// revert the view and be sure we can get the file now
 
@@ -1488,7 +1527,7 @@
 		File normFile = new File(projectPath.toFile(), "group/Icons_scalable.mk");
 		normFile.getParentFile().mkdir();
 		normFile.delete();
-		FileUtils.writeFileContents(normFile, text.toCharArray(), null);
+		FileUtils.writeFileContents(normFile, convertForOS(text).toCharArray(), null);
 
 		parserConfig.fileLocator = new BasicIncludeFileLocator(
 				new File[] { projectPath.append("inc").toFile() },
@@ -1524,7 +1563,7 @@
 
 		// the model should go into the main file, and the include removed
 		String newText = new String(FileUtils.readFileContents(normFile, null));
-		assertEquals("\r\n" + 
+		assertEquals(convertForOS("\r\n" + 
 				"SECURITY_FLAG=on\r\n" + 
 				"SCALABLE_FLAG=on\r\n" + 
 				"\r\n" + 
@@ -1532,11 +1571,11 @@
 				"		qgn_prop_nrtyp_date\r\n" + 
 				"	mifc$(SECURITY_FLAG)v foo.mif  \\\r\n" + 
 				"		 /c8,1 qgn_prop_nrtyp_date\r\n" + 
-				"", newText);
+				""), convertForOS(newText));
 		
 		// the include is unchanged
 		String newIncl = new String(FileUtils.readFileContents(incFile, null));
-		assertEquals(incl, newIncl);
+		assertEquals(convertForOS(incl), convertForOS(newIncl));
 		
 		referencedFiles = view.getReferencedFiles();
 		assertEquals(1, referencedFiles.length);
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -26,6 +26,7 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.IASTTopLevelNode;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.mmp.IASTMMPListArgumentStatement;
 import com.nokia.carbide.internal.cpp.epoc.engine.model.ViewASTBase;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.IMessage;
 
 import org.eclipse.core.runtime.IPath;
@@ -1049,7 +1050,7 @@
 		assertEquals(2, resource.getDependsFiles().size());
 		assertEquals("foo1.rsg", resource.getDependsFiles().get(0));
 		assertEquals("foo2.rsg", resource.getDependsFiles().get(1));
-		assertEquals(new Path("\\sys\\bin"), resource.getTargetPath());
+		assertEquals(new Path("/sys/bin"), resource.getTargetPath());
 		assertEquals("foo.rsc", resource.getTargetFile());
 		assertEquals(2, resource.getLanguages().size());
 		assertEquals(EGeneratedHeaderFlags.Header, resource.getHeaderFlags());
@@ -1101,7 +1102,7 @@
 	}
 
 	private void _testNewResourcesParsing2a(IMMPData data) {
-		assertEquals(new Path("\\sys\\target\\foo"), data.getTargetFilePath());
+		assertEquals(new Path("/sys/target/foo"), data.getTargetFilePath());
 		assertEquals("0x1", data.getUid2());
 		assertEquals("0x2", data.getUid3());
 		
@@ -1111,7 +1112,7 @@
 
 		assertEquals("foo1.rsg", resource.getDependsFiles().get(0));
 		assertEquals("foo2.rsg", resource.getDependsFiles().get(1));
-		assertEquals(new Path("\\sys\\bin"), resource.getTargetPath());
+		assertEquals(new Path("/sys/bin"), resource.getTargetPath());
 		assertEquals("0x3", resource.getUid2());
 		assertEquals("0x4", resource.getUid3());
 	}
@@ -1142,7 +1143,7 @@
 
 		assertEquals("foo1.rsg", resource.getDependsFiles().get(0));
 		assertEquals("foo2.rsg", resource.getDependsFiles().get(1));
-		assertEquals(new Path("\\sys\\bin"), resource.getTargetPath());
+		assertEquals(new Path("/sys/bin"), resource.getTargetPath());
 		assertEquals("0x3", resource.getUid2());
 		assertEquals("0x4", resource.getUid3());
 	}
@@ -1202,7 +1203,7 @@
 		assertEquals(1, resources.size());
 		IMMPResource resource = resources.get(0);
 		
-		resource.setTargetPath(new Path("\\sys\\data\\myapp"));
+		resource.setTargetPath(new Path("/sys/data/myapp"));
 		resource.getLanguages().add(EMMPLanguage.American);
 		
 		commitTest(view,
@@ -1221,7 +1222,7 @@
 		assertNotNull(view);
 		
 		IMMPResource resource = view.createMMPResource();
-		resource.setTargetPath(new Path("\\where"));
+		resource.setTargetPath(new Path("/where"));
 		resource.setTargetFile("targ.rsc");
 		assertFalse(resource.isValid());
 		resource.setSource(new Path("/foo/bar/data/uidesign.rss"));
@@ -1379,10 +1380,10 @@
 		makeModel("TARGETPATH \\foo\\bar\n"+
 				"TARGET file.exe\n");
 		IMMPView view = getView(mmpConfig);
-		assertEquals(new Path("\\foo\\bar\\file.exe"), view.getTargetFilePath());
+		assertEquals(new Path("/foo/bar/file.exe"), view.getTargetFilePath());
 		
 		// keep predom slash fmt
-		view.setTargetFilePath(new Path("\\sys\\bin\\nasty.exe"));
+		view.setTargetFilePath(new Path("/sys/bin/nasty.exe"));
 		commitTest(view, "TARGETPATH \\sys\\bin\n"+
 			"TARGET nasty.exe\n");
 		
@@ -1408,7 +1409,7 @@
 	private void _testAIFParsing0(IMMPData data) {
 		assertEquals(1, data.getAifs().size());
 		IMMPAIFInfo info = data.getAifs().get(0);
-		assertEquals(new Path("data\\aiffile.rss"), info.getResource());
+		assertEquals(new Path("data/aiffile.rss"), info.getResource());
 		// TARGETPATH not represented
 		assertEquals(new Path("targetfile.aif"), info.getTarget());
 		
@@ -1432,7 +1433,7 @@
 	private void _testAIFParsing1(IMMPData data) {
 		assertEquals(1, data.getAifs().size());
 		IMMPAIFInfo info = data.getAifs().get(0);
-		assertEquals(new Path("data\\aiffile.rss"), info.getResource());
+		assertEquals(new Path("data/aiffile.rss"), info.getResource());
 		// TARGETPATH not represented
 		assertEquals(new Path("targetfile.aif"), info.getTarget());
 
@@ -1638,7 +1639,7 @@
 		
 		IMMPBitmap bitmap = bitmaps.get(0);
 		assertEquals("foo.mbm", bitmap.getTargetFile());
-		assertEquals(new Path("\\sys\\pix"), bitmap.getTargetPath());
+		assertEquals(new Path("/sys/pix"), bitmap.getTargetPath());
 		assertEquals(EGeneratedHeaderFlags.Header, bitmap.getHeaderFlags());
 		assertEquals(3, bitmap.getSources().size());
 		
@@ -1673,7 +1674,10 @@
 		IMMPBitmap bitmap = view.createMMPBitmap();
 
 		bitmap.setTargetFile("target.mbm");
-		bitmap.setTargetPath(new Path("e:\\foo\\bar"));
+		if (HostOS.IS_WIN32)
+			bitmap.setTargetPath(new Path("e:\\foo\\bar"));
+		else
+			bitmap.setTargetPath(new Path("e:/foo/bar"));
 		bitmap.setHeaderFlags(EGeneratedHeaderFlags.Header);
 
 		IBitmapSource source = bitmap.createBitmapSource();
@@ -1701,10 +1705,15 @@
 	}
 	
 	public void testBitmapChanging1() {
+		String nativePath;
+		if (HostOS.IS_WIN32)
+			nativePath = "e:\\foo\\bar";
+		else
+			nativePath = "e:/foo/bar";
 		makeModel(
 				"START BITMAP target.mbm\n"+
 				"// comment 1\n"+
-				"\tTARGETPATH e:\\foo\\bar\n"+
+				"\tTARGETPATH "+ nativePath + "\n"+
 				"// comment 2\n"+
 				"\tHEADER\n"+
 				"// comment 3\n"+
@@ -1719,7 +1728,7 @@
 		IMMPBitmap bitmap = view.getBitmaps().get(0);
 
 		bitmap.setTargetFile("target.mbm");
-		bitmap.setTargetPath(new Path("e:\\foo\\bar"));
+		bitmap.setTargetPath(new Path(nativePath));
 		bitmap.setHeaderFlags(EGeneratedHeaderFlags.Header);
 
 		IBitmapSource source = (IBitmapSource) bitmap.getSources().get(0);
@@ -1733,7 +1742,7 @@
 		commitTest(view,
 				"START BITMAP target.mbm\n"+
 				"// comment 1\n"+
-				"\tTARGETPATH e:\\foo\\bar\n"+
+				"\tTARGETPATH " + nativePath + "\n"+
 				"// comment 2\n"+
 				"\tHEADER\n"+
 				"// comment 3\n"+
@@ -1746,11 +1755,16 @@
 		bitmap = view.getBitmaps().get(0);
 		bitmap.setHeaderFlags(EGeneratedHeaderFlags.HeaderOnly);
 		
-		// unfortunately we have to rewrite and lose comments here
+		// unfortunately we have to rewrite, reslash, and lose comments here 
+		String nativePix;
+		if (HostOS.IS_WIN32)
+			nativePix = "..\\data\\pix";
+		else
+			nativePix = "../data/pix";
 		commitTest(view,
 				"START BITMAP target.mbm\n"+
-				"\tTARGETPATH e:\\foo\\bar\n"+
-				"\tSOURCEPATH ..\\data\\pix\n"+
+				"\tTARGETPATH " +  nativePath + "\n"+
+				"\tSOURCEPATH " + nativePix + "\n"+
 				"\tSOURCE 8,8 icon.bmp icon_mask_soft.bmp\n"+
 				"\tHEADERONLY\n"+
 				"END\n");
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView2.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView2.java	Thu Dec 03 12:04:42 2009 -0600
@@ -32,12 +32,14 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.IASTTranslationUnit;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.mmp.IASTMMPStartBlockStatement;
 import com.nokia.carbide.internal.cpp.epoc.engine.model.ViewASTBase;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.IMessage;
 
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.text.IDocument;
 
+import java.io.File;
 import java.util.List;
 
 /**
@@ -92,44 +94,49 @@
 	public void testAbsolutePaths() {
 		// don't convert absolute or absolute-like paths
 		final String MMP = 
-			"USERINCLUDE +\\include\\oem \\epoc32\\foo c:\\foo\\bar\n";
+			"USERINCLUDE +\\include\\oem \\epoc32\\foo " + getTokenAbsolutePath() + "foo\\bar\n";
 		makeModel(MMP);
 		
 		IMMPView view = model.createView(mmpConfig);
 		IPath path = view.getUserIncludes().get(0);
-		assertEquals(new Path("+\\include\\oem"), path);
+		assertEquals(new Path("+/include/oem"), path);
 		path = view.getUserIncludes().get(1);
-		assertEquals(new Path("\\epoc32\\foo"), path);
+		assertEquals(new Path("/epoc32/foo"), path);
 		path = view.getUserIncludes().get(2);
-		assertEquals(new Path("c:\\foo\\bar"), path);
+		assertEquals(new Path(getTokenAbsolutePath()).append("/foo/bar"), path);
 
-		view.getSystemIncludes().add(new Path("+\\epoc32\\data"));
-		view.getSystemIncludes().add(new Path("\\epoc32\\user"));
+		view.getSystemIncludes().add(new Path("+/epoc32/data"));
+		view.getSystemIncludes().add(new Path("/epoc32/user"));
 		// NOTE: absolute paths with drive letters not allowed, so c:\ is dropped
 		// if a normal API using MMPViewPathHelper constructs the path.
 		// We don't strip anything inside MMPView because we don't know
 		// what future enhancements may need the letter.
-		view.getSystemIncludes().add(new Path("c:\\system\\files"));
+		view.getSystemIncludes().add(new Path(getTokenAbsolutePath()).append("system/files"));
+		
+		// since the other paths are backslash, we keep this in this forward-slash path
+		String expected = toDosPath(new Path(getTokenAbsolutePath()).append("system\\files"));
 		commitTest(view, MMP +
-				"SYSTEMINCLUDE +\\epoc32\\data \\epoc32\\user c:\\system\\files\n");
+				"SYSTEMINCLUDE +\\epoc32\\data \\epoc32\\user " + expected + "\n");
 	}
 	
 	public void testRootProject() {
 		// make sure we handle project root correctly when it's the root directory
+		String root = HostOS.IS_WIN32 ? "C:" : "/"; 
 		for (int i = 0; i < 2; i++){
-			parserConfig.projectPath = i == 0 ? new Path("c:\\") : new Path("c:");
-			this.path = new Path("c:\\symbian\\9.1\\S60_3rd\\S60Ex\\Hello\\group\\hello.mmp");
+			parserConfig.projectPath = new Path(i == 0 ? root : root + File.separator);
+			IPath base = new Path(getTokenAbsolutePath());
+			this.path = base.append("symbian/9.1/S60_3rd/S60Ex/Hello/group/hello.mmp");
 			makeModel("SOURCEPATH ..\\src\n"+
 					"SOURCE foo.cpp\n");
 			
 			IMMPView view = model.createView(mmpConfig);
 			IPath[] srcPaths = view.getEffectiveSourcePaths();
 			// important to be relative
-			assertEquals(new Path("symbian/9.1/S60_3rd/S60Ex/Hello/src"), srcPaths[0]);
+			assertEquals(base.makeRelative().setDevice(null).append("symbian/9.1/S60_3rd/S60Ex/Hello/src"), srcPaths[0]);
 	
 			IPath src = view.getSources().get(0);
 			// important to be relative
-			assertEquals(new Path("symbian/9.1/S60_3rd/S60Ex/Hello/src/foo.cpp"), src);
+			assertEquals(base.makeRelative().setDevice(null).append("symbian/9.1/S60_3rd/S60Ex/Hello/src/foo.cpp"), src);
 		}
 	}
 	
@@ -303,7 +310,8 @@
 	 *
 	 */
 	public void testBaseDirectory() {
-		parserConfig.getFilesystem().put(new Path("c:/test/basefile.mmp").toOSString(), 
+		IPath base = new Path(getTokenAbsolutePath()).append("test/basefile.mmp");
+		parserConfig.getFilesystem().put(base.toOSString(), 
 				"SOURCEPATH .\n"+
 				"SOURCE base.cpp\n");
 
@@ -314,7 +322,7 @@
 		makeModel(
 				"SOURCEPATH .\n"+
 				"SOURCE first.cpp\n"+
-				"#include \"c:\\test\\basefile.mmp\"\n"+
+				"#include \"" + base.toOSString() + "\"\n"+
 				"#include \"../utils/helper.mmh\"\n"+
 				"SOURCEPATH ../src\n"+
 				"SOURCE last.cpp\n");
@@ -325,7 +333,7 @@
 		assertEquals(new Path("group/first.cpp"), view.getSources().get(0));
 		
 		// note: should not be relative path when outside the project
-		assertEquals(new Path("c:/test/base.cpp"), view.getSources().get(1));
+		assertEquals(base.removeLastSegments(1).append("base.cpp"), view.getSources().get(1));
 		
 		assertEquals(new Path("utils/helper.cpp"), view.getSources().get(2));
 		assertEquals(new Path("src/last.cpp"), view.getSources().get(3));
@@ -730,7 +738,7 @@
 				"*  Description : Music Collection Common project specification\r\n" + 
 				"*  Version     : 1.0\r\n" + 
 				"*\r\n" + 
-				"*  Copyright © 2004 Nokia. All rights reserved.\r\n" + 
+				"*  Copyright (c) 2004 Nokia. All rights reserved.\r\n" + 
 				"*  This material, including documentation and any related \r\n" + 
 				"*  computer programs, is protected by copyright controlled by \r\n" + 
 				"*  Nokia. All rights are reserved. Copying, including \r\n" + 
@@ -844,7 +852,7 @@
 			"*  Description : Music Collection project specification\r\n" + 
 			"*  Version     : \r\n" + 
 			"*\r\n" + 
-			"*  Copyright © 2004 Nokia. All rights reserved.\r\n" + 
+			"*  Copyright (c) 2004 Nokia. All rights reserved.\r\n" + 
 			"*  This material, including documentation and any related \r\n" + 
 			"*  computer programs, is protected by copyright controlled by \r\n" + 
 			"*  Nokia. All rights are reserved. Copying, including \r\n" + 
@@ -1183,26 +1191,32 @@
 	public void testNoDriveLettersAppear() {
 		makeModel("USERINCLUDE ..\\group\n");
 		IMMPView view = model.createView(mmpConfig);
-		view.getUserIncludes().add(new Path("c:\\temp"));
+		IPath fullpath = new Path(getTokenAbsolutePath()).append("temp");
+		view.getUserIncludes().add(fullpath);
 		// We don't strip drive letters inside the MMPView, only through the
 		// canonicalization API MMPViewPathHelper.
 		commitTest(view,
-				"USERINCLUDE ..\\group c:\\temp\n");
+				"USERINCLUDE ..\\group " + toDosPath(fullpath) + "\n");
 	}
 	public void testNoDriveLettersAppear2() {
+		// not going to have a drivey path here
+		if (HostOS.IS_UNIX)
+			return;
+		
 		makeModel("USERINCLUDE ..\\group\n");
 		IMMPView view = model.createView(mmpConfig);
 		MMPViewPathHelper helper = new MMPViewPathHelper(view, (IPath)null);
 		try {
 			// no SDK active here, so all full paths throw
 			helper.convertProjectOrFullPathToMMP(
-								EMMPPathContext.USERINCLUDE, new Path("c:\\temp"));
+								EMMPPathContext.USERINCLUDE, new Path(getTokenAbsolutePath()).append("temp"));
 			fail();
 		} catch (InvalidDriveInMMPPathException e) {
 			view.getUserIncludes().add(e.getPathNoDevice());
 		}
+		IPath fullpath = new Path(getTokenAbsolutePath()).setDevice(null).append("temp");
 		commitTest(view,
-				"USERINCLUDE ..\\group \\temp\n");
+				"USERINCLUDE ..\\group " + toDosPath(fullpath) + "\n");
 	}
 	
 	public void testBug2817() {
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView3.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView3.java	Thu Dec 03 12:04:42 2009 -0600
@@ -28,6 +28,7 @@
 import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
 import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
 import com.nokia.carbide.cpp.sdk.core.SymbianSDKFactory;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 
 import org.eclipse.core.runtime.*;
 import org.osgi.framework.Version;
@@ -115,7 +116,7 @@
 		// if we got here, now try converting back 
 		boolean isFixedDirectory = false;
 		String origDefFile = mmpView.getSingleArgumentSettings().get(EMMPStatement.DEFFILE);
-		if (origDefFile != null && new Path(origDefFile).segmentCount() > 1)
+		if (origDefFile != null && new Path(HostOS.convertPathToUnix(origDefFile)).segmentCount() > 1)
 			isFixedDirectory = true;
 		mmpView.setDefFile(realPath, isFixedDirectory);
 		IPath convPath = mmpView.getDefFile();
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView4.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMMPView4.java	Thu Dec 03 12:04:42 2009 -0600
@@ -1009,7 +1009,7 @@
 		makeModel(text);
 		view = getView(mmpConfig);
 		
-		view.getSystemIncludes().set(1, new Path("\\epoc32\\foo"));
+		view.getSystemIncludes().set(1, new Path("/epoc32/foo"));
 		commitTest(view, text5);
 		
 	}
@@ -1065,7 +1065,7 @@
 		makeModel(text);
 		view = getView(mmpConfig);
 		
-		view.getSystemIncludes().set(1, new Path("\\epoc32\\arglebargle"));
+		view.getSystemIncludes().set(1, new Path("/epoc32/arglebargle"));
 		commitTest(view, text4);
 		
 	}
@@ -1122,7 +1122,7 @@
 		makeModel(text);
 		view = getView(mmpConfig);
 		
-		view.getSystemIncludes().set(1, new Path("\\epoc32\\arglebargle"));
+		view.getSystemIncludes().set(1, new Path("/epoc32/arglebargle"));
 		commitTest(view, text4);
 		
 	}
@@ -1181,7 +1181,7 @@
 			checkNoProblems(view);
 			
 			IPath path = view.getSystemIncludes().get(0);
-			assertEquals(new Path("\\src\\cedar\\generic\\base\\e32\\drivers\\pbus\\mmc\\sdcard\\sdcard3c"), 
+			assertEquals(new Path("/src/cedar/generic/base/e32/drivers/pbus/mmc/sdcard/sdcard3c"), 
 					path);
 			
 			
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMakefileView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestMakefileView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -27,6 +27,7 @@
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.IDefine;
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.IViewFilter;
 import com.nokia.carbide.cpp.epoc.engine.tests.BaseTest;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.IMessage;
 
 import org.eclipse.cdt.make.core.makefile.ICommand;
@@ -86,6 +87,9 @@
 	}
 	
 	protected void makeModel(String text) {
+		// TODO: tests should work with both slash directions on both OSes
+		if (HostOS.IS_UNIX)
+			text = text.replaceAll("\\\\(?!\r|\n)", "/");
 		IDocument document = DocumentFactory.createDocument(text);
 		model = new MakefileModelFactory().createModel(path, document);
 
@@ -99,6 +103,9 @@
 	}
 	
 	protected void commitTest(IMakefileView view, String refText) {
+		// TODO: tests should work with both slash directions on both OSes
+		if (HostOS.IS_UNIX)
+			refText = refText.replaceAll("\\\\(?!\r|\n)", "/");
 		commitTest(model, view, refText);
 	}
 	
@@ -182,8 +189,9 @@
 		assertEquals(1, commands.length);
 		assertNotNull(commands[0].getParent());
 	
+		String mifconvEXELine = "MIFCONV=$(TOOLDIR)\\mifconv"+ (HostOS.IS_WIN32 ? ".exe" : "") + "\n";  
 		makeModel("TOOLSDIR=c:\\my\\tools\n"+
-				"MIFCONV=$(TOOLDIR)\\mifconv.exe\n"+
+				mifconvEXELine +
 				"\n"+
 				"all: mytool\n"+
 				"\n"+
@@ -206,7 +214,7 @@
 		view.replaceDirective(oldRule, newRule);
 
 		commitTest(view, "TOOLSDIR=c:\\my\\tools\n"+
-				"MIFCONV=$(TOOLDIR)\\mifconv.exe\n"+
+				mifconvEXELine +
 				"\n"+
 				"all: mytool\n"+
 				"\n"+
@@ -365,34 +373,48 @@
 
 	}
 	
-	public void testUnexpand() {
+	public void testUnexpand1() {
 		makeModel("ZDIR=$(EPOCROOT)\\release\\winscw\n"+
 				"TARGETDIR=$(ZDIR)\\data\n"+
 				"ICONTARGETFILENAME=$(TARGETDIR)\\foo.mif\n");
 		IMakefileView view = getView(viewConfig);
 
-		String repl = view.unexpandMacros("$(EPOCROOT)\\release\\winscw\\data\\more.mif", 
-				new String[] {  "TARGETDIR", "ZDIR" });
-		assertEquals("$(TARGETDIR)\\more.mif", repl);
+		doUnexpandTest(view, "$(EPOCROOT)\\release\\winscw\\data\\more.mif", 
+				"$(TARGETDIR)\\more.mif");
 
-		String repl1 = view.unexpandMacros("1 2 $(EPOCROOT)\\release\\winscw\\data\\more.mif 3 4", 
-				new String[] {  "TARGETDIR", "ZDIR" });
-		assertEquals("1 2 $(TARGETDIR)\\more.mif 3 4", repl1);
+		doUnexpandTest(view, "1 2 $(EPOCROOT)\\release\\winscw\\data\\more.mif 3 4", 
+			"1 2 $(TARGETDIR)\\more.mif 3 4");
 
-		String repl2 = view.unexpandMacros("$(EPOCROOT)\\release\\winscw\\more.mif", 
-				new String[] {  "TARGETDIR", "ZDIR" });
-		assertEquals("$(ZDIR)\\more.mif", repl2);
+		doUnexpandTest(view, "$(EPOCROOT)\\release\\winscw\\more.mif", 
+			"$(ZDIR)\\more.mif");
 
-		String repl3 = view.unexpandMacros("$(EPOCROOT)\\release\\foo\\data\\more.mif", 
-				new String[] {  "TARGETDIR", "ZDIR" });
-		assertEquals("$(EPOCROOT)\\release\\foo\\data\\more.mif", repl3);
+		doUnexpandTest(view, "$(EPOCROOT)\\release\\foo\\data\\more.mif", 
+			"$(EPOCROOT)\\release\\foo\\data\\more.mif");
 
-		String repl4 = view.unexpandMacros("\\release\\winscw\\data\\more.mif", 
-				new String[] {  "TARGETDIR", "ZDIR" });
-		assertEquals("\\release\\winscw\\data\\more.mif", repl4);
+		doUnexpandTest(view, "\\release\\winscw\\data\\more.mif", 
+			"\\release\\winscw\\data\\more.mif");
 
 	}
 	
+	
+	private void doUnexpandTest(IMakefileView view, String expanded,
+			String unexpanded) {
+
+		// TODO: tests should ideally work with both slash directions on both OSes
+		if (HostOS.IS_WIN32) {
+			String repl = view.unexpandMacros(expanded, 
+					new String[] {  "TARGETDIR", "ZDIR" });
+			assertEquals(unexpanded, repl);
+		} else {
+			expanded = HostOS.convertPathToUnix(expanded);
+			unexpanded = HostOS.convertPathToUnix(unexpanded);
+			String repl = view.unexpandMacros(expanded, 
+					new String[] {  "TARGETDIR", "ZDIR" });
+			assertEquals(unexpanded, repl);
+		}
+		
+	}
+
 	public void testProblems() {
 		makeModel("\n\n)ZDIR@foo{\n"+
 				"^^ placate ^^\n");
--- a/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestViewDataCache.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine.tests/src/com/nokia/carbide/cpp/epoc/engine/tests/model/TestViewDataCache.java	Thu Dec 03 12:04:42 2009 -0600
@@ -60,9 +60,13 @@
 	private File tmpDir;
 	private File projectDir;
 
+	// Try to wait long enough to ensure the timestamp-based check will detect a change
+	private static final long FS_TIME_RESOLUTION = ViewDataCache.ModelFileTimestampCollection.MIN_TIMESTAMP_RESOLUTION;
+	
 	/* (non-Javadoc)
 	 * @see com.nokia.carbide.cpp.epoc.engine.tests.BaseTest#setUp()
 	 */
+	@SuppressWarnings("unchecked")
 	protected void setUp() throws Exception {
 		super.setUp();
 		modelProvider = ModelProviderFactory.createModelProvider(new MMPModelFactory());
@@ -123,12 +127,12 @@
 		assertEquals(new Path("group/foo.cpp"), data.getSources().get(0));
 		
 		// change foo.mmp on disk
-		Thread.sleep(50);
+		Thread.sleep(FS_TIME_RESOLUTION);
 		makeFile("group/foo.mmp",
 				"SOURCEPATH .\n"+
-				"SOURCE foo.cpp bar.cpp\n");
+				"SOURCE foo.cpp bar.cpp\n");		// note: size changes too
 		// cache throttles file timestamp checks
-		Thread.sleep(55);
+		Thread.sleep(FS_TIME_RESOLUTION);
 
 		IMMPData data2 = viewDataCache.getData(mmpPath, new DefaultMMPViewConfiguration(projectPath));
 		assertNotNull(data2);
@@ -154,12 +158,12 @@
 		assertEquals("0x6000", data.getSingleArgumentSettings().get(EMMPStatement.BASEADDRESS));
 		
 		// change foo.mmh on disk
-		Thread.sleep(5);
+		Thread.sleep(FS_TIME_RESOLUTION);
 		makeFile("group/header.mmh",
-				"BASEADDRESS 0x1111");
+				"BASEADDRESS 0x1111");	// note: size does not change
 		
 		// cache throttles disk time checks
-		Thread.sleep(55);
+		Thread.sleep(FS_TIME_RESOLUTION);
 		
 		IMMPData data2 = viewDataCache.getData(mmpPath, new DefaultMMPViewConfiguration(projectPath));
 		assertNotNull(data2);
@@ -354,6 +358,7 @@
 				data = viewDataCache.getData(path, config);
 				data = viewDataCache.getData(path, config);
 				data = viewDataCache.getData(path, config);
+				if (data != null) ; // read to squash warning
 			} catch (CoreException e) {
 				throw new RuntimeException(e);
 			}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/cpp/epoc/engine/image/ImageFormat.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/cpp/epoc/engine/image/ImageFormat.java	Thu Dec 03 12:04:42 2009 -0600
@@ -27,7 +27,7 @@
  */
 public class ImageFormat {
 	// tolerate but ignore extra 'c'
-	private static final Pattern FORMAT_PATTERN = Pattern.compile("/?(c?)(\\d+)(,c?(\\d+))?", //$NON-NLS-1$
+	private static final Pattern FORMAT_PATTERN = Pattern.compile("[/-]?(c?)(\\d+)(,c?(\\d+))?", //$NON-NLS-1$
 			Pattern.CASE_INSENSITIVE);
 	public boolean isColor;
 	public int depth;
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/cpp/epoc/engine/model/makefile/ArgList.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/cpp/epoc/engine/model/makefile/ArgList.java	Thu Dec 03 12:04:42 2009 -0600
@@ -38,7 +38,7 @@
 	public ArgList(String text) {
 		String trimmed = text.trim();
 		this.initial = text.substring(0, text.indexOf(trimmed));
-		this.terminal = text.substring(text.length() - this.initial.length() - trimmed.length());
+		this.terminal = text.substring(text.length() - this.initial.length());
 		this.argv = splitArguments(trimmed);
 		
 	}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/api/cpp/epoc/engine/preprocessor/BasicIncludeFileLocator.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/api/cpp/epoc/engine/preprocessor/BasicIncludeFileLocator.java	Thu Dec 03 12:04:42 2009 -0600
@@ -26,6 +26,7 @@
 import java.io.IOException;
 
 import com.nokia.carbide.cpp.epoc.engine.preprocessor.IIncludeFileLocator;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 public class BasicIncludeFileLocator implements IIncludeFileLocator {
 
 	private static final File[] NO_DIRS = new File[0];
@@ -43,6 +44,10 @@
 	}
 	
 	public File findIncludeFile(String file, boolean isUser, File currentDir) {
+		if (HostOS.IS_UNIX) {
+			file = HostOS.convertPathToUnix(file);
+		}
+		
 		// see if the file exists as an absolute file
 		File theFile = new File(file);
 		if (theFile.exists() && theFile.isFile() && theFile.isAbsolute())
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/image/AifdefFileConverter.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/image/AifdefFileConverter.java	Thu Dec 03 12:04:42 2009 -0600
@@ -98,7 +98,7 @@
 					// but only .mbmdef available in Carbide UI
 					String mbmdefFile = matcher.group(3);
 					IPath mbmdefPath = resolver.resolvePath(projectPath.append(mbmdefFile).toOSString());
-					if (mbmdefPath.getDevice() == null)
+					if (mbmdefPath.getDevice() == null && (!HostOS.IS_WIN32 && !mbmdefPath.isAbsolute()))
 						mbmdefPath = new Path(projectPath.removeTrailingSeparator().lastSegment()).append(mbmdefPath);
 					String mbmdefText = readFileText(mbmdefPath);
 					IMultiImageSource multiImageSource = new MbmdefFileConverter().convert(targetPath, mbmdefFile, mbmdefText, resolver);
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/image/MultiImageSource.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/image/MultiImageSource.java	Thu Dec 03 12:04:42 2009 -0600
@@ -102,7 +102,7 @@
 
 	public IPath getDefaultGeneratedHeaderFilePath() {
 		String fileName = targetFile != null && targetFile.length() > 0 ? targetFile : "<unnamed>"; //$NON-NLS-1$
-		return new Path("epoc32\\include").append(fileName).removeFileExtension().addFileExtension("mbg");	 //$NON-NLS-1$ //$NON-NLS-2$
+		return new Path("epoc32/include").append(fileName).removeFileExtension().addFileExtension("mbg");	 //$NON-NLS-1$ //$NON-NLS-2$
 	}
 
 	/* (non-Javadoc)
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/ViewBase.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/ViewBase.java	Thu Dec 03 12:04:42 2009 -0600
@@ -447,13 +447,13 @@
 	}
 	
 	public IPath convertModelToProjectPath(IPath modelPath) {
-		if (modelPath == null || modelPath.isAbsolute())
+		if (modelPath == null || isAbsolutePath(modelPath))
 			return modelPath;
 		return fromProjectToRelativePath(getProjectPath(), model.getPath().removeLastSegments(1).append(modelPath), true);
 	}
 	
 	public IPath convertProjectToModelPath(IPath prjPath) {
-		if (prjPath == null || prjPath.isAbsolute())
+		if (prjPath == null || isAbsolutePath(prjPath))
 			return prjPath;
 		return fromProjectToRelativePath(model.getPath().removeLastSegments(1), getProjectPath().append(prjPath));
 	}
@@ -560,4 +560,25 @@
 		else
 			return '\\';
 	}
+
+	/**
+	 * Tell if the path is a Win32 path with drive letter or UNC.
+	 * @param path
+	 */
+	public static boolean isWin32DrivePath(IPath path) {
+		return path.getDevice() != null 
+			|| (!HostOS.IS_WIN32 && path.segmentCount() > 0 && path.segment(0).matches("[A-Za-z]:"));
+	}
+
+	/**
+	 * Tell if the path is absolute -- e.g., according to the host or to Windows conventions.
+	 * @param path
+	 */
+	public static boolean isAbsolutePath(IPath path) {
+		if (path.isAbsolute())
+			return true;
+		if (isWin32DrivePath(path))
+			return true;
+		return false;
+	}
 }
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/ViewDataCache.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/ViewDataCache.java	Thu Dec 03 12:04:42 2009 -0600
@@ -164,49 +164,72 @@
 		
 	}
 
-	static class FileTimestampCollection {
-		private static FileTimestampCollection instance;
+	static class FileTimestampSizeCollection {
+		static FileTimestampSizeCollection INSTANCE = new FileTimestampSizeCollection();
 		/** Check timestamps only once in this number of milliseconds */
 		final int QUANTUM = 0;
-		/** map of file to last queried timestamp + time of last query */
-		private Map<File, Pair<Long, Long>> timestamps;		
 		
-		public static FileTimestampCollection getInstance() {
-			if (instance == null) {
-				instance = new FileTimestampCollection();
+		static class FileInfo extends Tuple {
+			public FileInfo(long lastModified, long lastQueried, long size) {
+				super(lastModified, lastQueried, size);
+			}
+			public long getLastModified() {
+				return (Long) get(0);
 			}
-			return instance;
+			public long getLastQueried() {
+				return (Long) get(0);
+			}
+			public long getLength() { 
+				return (Long) get(2);
+			}
 		}
+		/** map of file to file size + last queried timestamp + time of last query 
+		 * (use File, not IPath, so we canonicalize for the OS) */
+		private Map<File, FileInfo> info = new HashMap<File, FileInfo>();		
 		
-		private FileTimestampCollection() {
-			timestamps = new HashMap<File, Pair<Long, Long>>();
-		}
-
+		
 		/** Tell if the file's timestamp changed in the past quantum 
 		 * and update the record */
 		public boolean changed(File file) {
 			long now = System.currentTimeMillis();
-			Pair<Long, Long> stamp = timestamps.get(file);
-			if (stamp == null) {
-				stamp = new Pair<Long, Long>(file.lastModified(), now);
-				timestamps.put(file, stamp);
+			FileInfo finfo = info.get(file);
+			if (finfo == null) {
+				finfo = new FileInfo(file.lastModified(), now, file.length());
+				info.put(file, finfo);
+				if (DEBUG) System.out.println("First info for " + file + ": " + finfo);
 				return true;
-			} else if (stamp.second + QUANTUM < now) {
+			} else if (finfo.getLastQueried() + QUANTUM < now) {
 				// don't check times more than QUANTUM
-				long origTime = stamp.first;
-				stamp = new Pair<Long, Long>(file.lastModified(), now);
-				timestamps.put(file, stamp);
-				return origTime != stamp.first;
+				long origTime = finfo.getLastModified();
+				long origSize = finfo.getLength();
+				finfo = new FileInfo(file.lastModified(), now, file.length());
+				info.put(file, finfo);
+				if (DEBUG) System.out.println("Updated info for " + file + ": " + origTime + "/" + origSize + " <=> " 
+						+ finfo.getLastModified() + "/" + finfo.getLength());
+				return origTime != finfo.getLastModified() || finfo.getLastModified() == 0 // 0 if deleted
+					|| origSize != finfo.getLength();		
 			} else {
-				// not changed
+				// not changed, as far as we assume
+				if (DEBUG) System.out.println("Assuming no change for " + file);
 				return false;
 			}
 		}
 	}
 	
-	static class ModelFileTimestampCollection {
-
-		private static final long QUANTUM = 50;
+	public static class ModelFileTimestampCollection {
+		/**
+		 * The minimum timestamp resolution for a file in ms (based on heuristics for the OS).
+		 * VFAT on Win32 uses 2 second increments.  Linux ext2/3 uses 1 second resolution, 
+		 * until ext4, where it becomes nanoseconds.
+		 * Assume the worst format in all cases.
+		 */
+		public static final long MIN_TIMESTAMP_RESOLUTION = HostOS.IS_WIN32 ? 2000 : 1000;
+		/**
+		 * Delay in ms between successive checks of the filesystem, to avoid wasting time
+		 * when such checks are slow, and in cases where it's unlikely the human will edit files
+		 * fast enough to care.
+		 */
+		public static final long QUANTUM = HostOS.IS_WIN32 ? 50 : 10;
 		private File[] files;
 		private long lastQuery;
 
@@ -217,7 +240,7 @@
 			for (IPath path : paths) {
 				files[idx] = path.toFile();
 				// prime the cache
-				FileTimestampCollection.getInstance().changed(files[idx]);
+				FileTimestampSizeCollection.INSTANCE.changed(files[idx]);
 				idx++;
 			}
 			this.lastQuery = System.currentTimeMillis();
@@ -230,11 +253,15 @@
 		public boolean changed() {
 			long prevQuery = lastQuery;
 			lastQuery = System.currentTimeMillis();
-			if (prevQuery + QUANTUM > lastQuery)
+			
+			// don't check more often than the resolution of the file allows
+			if (prevQuery + QUANTUM > lastQuery) {
+				if (DEBUG) System.out.println("Skipping fileinfo check");
 				return false;
+			}
 			
 			for (File file : files) {
-				if (FileTimestampCollection.getInstance().changed(file)) {
+				if (FileTimestampSizeCollection.INSTANCE.changed(file)) {
 					return true;
 				}
 			}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/bldinf/BldInfView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/bldinf/BldInfView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -41,7 +41,7 @@
 	/**
 	 * 
 	 */
-	public static final String EPOC32_INCLUDE = "\\epoc32\\include"; //$NON-NLS-1$
+	public static final String EPOC32_INCLUDE = "/epoc32/include"; //$NON-NLS-1$
 	public static final String ZIP_MODIFIER = ":zip"; //$NON-NLS-1$
 	public static final String PRJ_EXPORTS_KEYWORD = "PRJ_EXPORTS"; //$NON-NLS-1$
 	public static final String PRJ_TESTEXPORTS_KEYWORD = "PRJ_TESTEXPORTS"; //$NON-NLS-1$
@@ -105,7 +105,11 @@
 	 * @return
 	 */
 	private IPath fromBldInfToProjectPath(IPath bldinfPath) {
-		IPath path = currentDirectory != null && !bldinfPath.isAbsolute() ? currentDirectory.append(bldinfPath) : bldinfPath;
+		IPath path;
+		if (currentDirectory != null && !isAbsolutePath(bldinfPath))
+			path = currentDirectory.append(bldinfPath);
+		else
+			path = bldinfPath;
 		if (FileUtils.isPathInParent(path)) {
 			path = getProjectPath().append(path);
 		}
@@ -136,7 +140,7 @@
 	 * @return BldInf-relative directory 
 	 */
 	IPath fromProjectToBldInfPath(IPath projectPath) {
-		if (projectPath.isAbsolute())
+		if (isAbsolutePath(projectPath))
 			return projectPath;
 		return fromProjectToRelativePath(currentDirectory, projectPath);
 	}
@@ -277,7 +281,7 @@
 				path = fromBldInfToProjectPath(pathName.substring(1));
 			} else {
 				path = FileUtils.createPossiblyRelativePath(pathName);
-				if (!path.isAbsolute())
+				if (!isAbsolutePath(path))
 					path = new Path(EPOC32_INCLUDE).append(path);
 			}
 		}
@@ -311,7 +315,7 @@
 				} else {
 					return epocIncludeRelPath;
 				}
-			} else if (!projectPath.isAbsolute()) {
+			} else if (!isAbsolutePath(projectPath)) {
 				// project-relative
 				return new Path("|" + fromProjectToBldInfPath(projectPath).toString());
 			}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/bldinf/ExportListConverter.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/bldinf/ExportListConverter.java	Thu Dec 03 12:04:42 2009 -0600
@@ -25,6 +25,7 @@
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.bldinf.ASTBldInfFactory;
 import com.nokia.carbide.internal.api.cpp.epoc.engine.dom.bldinf.IASTBldInfExportStatement;
 import com.nokia.carbide.internal.cpp.epoc.engine.model.StructuredItemStatementListConverter;
+import com.nokia.carbide.internal.cpp.epoc.engine.model.ViewBase;
 import com.nokia.cpp.internal.api.utils.core.*;
 
 import org.eclipse.core.runtime.IPath;
@@ -90,9 +91,9 @@
 		if (targetPath != null) {
 			// need the backslashes for an export to a drive, else the build rules are broken
 			// (they use 'copy' in DOS which doesn't like forward slashes)
-			if (targetPath.getDevice() != null) {
-				target = targetPath.toOSString();
-				source = sourcePath.toOSString();
+			if (ViewBase.isWin32DrivePath(targetPath)) {
+				target = HostOS.convertPathToWindows(targetPath.toOSString());
+				source = HostOS.convertPathToWindows(sourcePath.toOSString());
 			}
 			else
 				target = bldInfView.pathString(targetPath);
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/makefile/MakefileViewBase.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/makefile/MakefileViewBase.java	Thu Dec 03 12:04:42 2009 -0600
@@ -51,6 +51,8 @@
 	private String eol;
 	private HashMap<String, IPath> directiveFilenameToPathMap;
 	private Set<IPath> referencedFiles;
+	private VariableSubstitutionEngine engine;
+	private IVariableLookupCallback engineSubstitutor;
 	
 	/**
 	 * @param model
@@ -351,7 +353,7 @@
 	protected String getProgramMatcherPattern(String program) {
 		String ext = ""; //$NON-NLS-1$
 		program = makefile.expandString(program, true);
-		if (!Platform.isRunning() || Platform.getOS().equals(Platform.OS_WIN32)) {
+		if (HostOS.IS_WIN32) {
 			ext = ".exe"; //$NON-NLS-1$
 			if (program.length() > 4 && program.substring(program.length() - 4).equalsIgnoreCase(ext)) {
 				program = program.substring(0, program.length() - 4);
@@ -577,11 +579,25 @@
 		return vars;
 	}
 
-	private String substituteMacros(Map<String, String> vars, String text) {
-		VariableSubstitutionEngine engine = new VariableSubstitutionEngine(null, null);
-		engine.allowRecursion(true);
-		engine.setVariableToken('(');
-		return engine.substitute(vars, text);
+	private String substituteMacros(final Map<String, String> vars, String text) {
+		if (engine == null) {
+			engine = new VariableSubstitutionEngine(null, null);
+			engine.allowRecursion(true);
+			engine.setVariableToken('(');
+			
+			engineSubstitutor = new IVariableLookupCallback() {
+				
+				public Object getValue(String var) {
+					String value = vars.get(var);
+					if (value == null)
+						return null;
+					if (HostOS.IS_UNIX)
+						value = HostOS.convertPathToUnix(value);
+					return value;
+				}
+			};
+		}
+		return engine.substitute(engineSubstitutor, text);
 	}
 
 	/* (non-Javadoc)
@@ -702,7 +718,7 @@
 	 */
 	@Override
 	public IPath convertModelToProjectPath(IPath modelPath) {
-		if (modelPath.isAbsolute() || modelPath.toString().startsWith("$")) //$NON-NLS-1$
+		if (isAbsolutePath(modelPath) || modelPath.toString().startsWith("$")) //$NON-NLS-1$
 			return modelPath;
 
 		return super.convertModelToProjectPath(modelPath);
@@ -713,7 +729,7 @@
 	 */
 	@Override
 	public IPath convertProjectToModelPath(IPath prjPath) {
-		if (prjPath.isAbsolute() || prjPath.toString().startsWith("$")) //$NON-NLS-1$
+		if (isAbsolutePath(prjPath) || prjPath.toString().startsWith("$")) //$NON-NLS-1$
 			return prjPath;
 
 		return super.convertProjectToModelPath(prjPath);
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/makefile/image/MifConvCommandLineConverter.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/makefile/image/MifConvCommandLineConverter.java	Thu Dec 03 12:04:42 2009 -0600
@@ -22,6 +22,7 @@
 import com.nokia.carbide.cpp.epoc.engine.model.EGeneratedHeaderFlags;
 import com.nokia.carbide.cpp.epoc.engine.model.makefile.ArgList;
 import com.nokia.carbide.cpp.epoc.engine.model.makefile.image.*;
+import com.nokia.carbide.internal.cpp.epoc.engine.model.ViewBase;
 import com.nokia.cpp.internal.api.utils.core.*;
 
 import org.eclipse.core.runtime.*;
@@ -38,11 +39,19 @@
 public class MifConvCommandLineConverter implements
 		IImageBuilderCommandLineConverter {
 
-	static final Pattern HEADER_PATTERN = Pattern.compile("/H(.*)", //$NON-NLS-1$
+	// The original syntax used slash options, but these look like paths in Unix,
+	// so mifconv changed to use dash options.  We originally generated slash options
+	// so we need to support both, but generate dash options now.
+	static final String OPTION_CHARS = HostOS.IS_WIN32 ? "[/-]" : "-";
+	
+	// TODO: still prefer '/' in Win32 until we fix unit tests and templates
+	static final char OUT_OPTION_CHAR = HostOS.IS_WIN32 ? '/' : '-';
+	
+	static final Pattern HEADER_PATTERN = Pattern.compile(OPTION_CHARS + "H(.*)", //$NON-NLS-1$
 			Pattern.CASE_INSENSITIVE);
-	static final Pattern PARAM_FILE_PATTERN = Pattern.compile("/F(.*)", //$NON-NLS-1$
+	static final Pattern PARAM_FILE_PATTERN = Pattern.compile(OPTION_CHARS + "F(.*)", //$NON-NLS-1$
 			Pattern.CASE_INSENSITIVE);
-	static final Pattern EXTENSIONS_PATTERN = Pattern.compile("/E", //$NON-NLS-1$
+	static final Pattern EXTENSIONS_PATTERN = Pattern.compile(OPTION_CHARS + "E", //$NON-NLS-1$
 			Pattern.CASE_INSENSITIVE);
 	private static final Pattern SVG_EXTENSION_PATTERN = Pattern.compile("svgt?", //$NON-NLS-1$
 			Pattern.CASE_INSENSITIVE);
@@ -50,7 +59,7 @@
 			Pattern.CASE_INSENSITIVE);
 	private static final String EPOCROOT_SUBSTITUTION = "$(EPOCROOT)"; //$NON-NLS-1$
 	private static final String ZDIR_SUBSTITUTION = "$(ZDIR)"; //$NON-NLS-1$
-	private static final String ZDIR_CONTENTS = "epoc32\\data\\z"; //$NON-NLS-1$
+	private static final String ZDIR_CONTENTS = HostOS.IS_WIN32 ? "epoc32\\data\\z" : "epoc32/data/z"; //$NON-NLS-1$ //$NON-NLS-2$
 	
 	// tracked during parsing (non-reentrant!)
 	private ImageFormat imageFormat;
@@ -161,8 +170,8 @@
 				continue;
 			}
 
-			// unused option
-			if (arg.startsWith("/")) //$NON-NLS-1$
+			// unused option (or filename)
+			if (arg.matches(OPTION_CHARS + ".*") && !arg.toLowerCase().matches(".*\\.(bmp|svg).*")) //$NON-NLS-1$ //$NON-NLS-2$
 				continue;
 			
 			// if image format not set, unknown garbage
@@ -209,7 +218,7 @@
 	 */
 	private List<String> readParamFile(IImageMakefileView view, String filename) {
 		IPath filePath = FileUtils.createPossiblyRelativePath(filename);
-		if (!filePath.isAbsolute() && !filePath.toString().startsWith("$")) {
+		if (!ViewBase.isAbsolutePath(filePath) && !filePath.toString().startsWith("$")) {
 			filePath = view.getModelPath().removeLastSegments(1).append(filePath);
 		}
 		File file = filePath.toFile();
@@ -222,7 +231,7 @@
 			ArgList list = new ArgList(text);
 			return list.getArgv();
 		} catch (CoreException e) {
-			return Collections.EMPTY_LIST;
+			return Collections.emptyList();
 		}
 	}
 
@@ -277,30 +286,30 @@
 			if (generatedHeaderFilePath == null) {
 				generatedHeaderFilePath = multiImageSource.getDefaultGeneratedHeaderFilePath();
 			}
-			if (!generatedHeaderFilePath.isAbsolute() && !generatedHeaderFilePath.toString().startsWith(EPOCROOT_SUBSTITUTION)) {
+			if (!ViewBase.isAbsolutePath(generatedHeaderFilePath) && !generatedHeaderFilePath.toString().startsWith(EPOCROOT_SUBSTITUTION)) {
 				generatedHeaderFilePath = new Path(EPOCROOT_SUBSTITUTION + generatedHeaderFilePath.toOSString());
 			}
 			file = fromProjectToMakefilePath(view, generatedHeaderFilePath);
 			
-			arg = "/H" + view.unexpandMacros(file.toOSString(), //$NON-NLS-1$
+			arg = OUT_OPTION_CHAR + "H" + view.unexpandMacros(file.toOSString(), //$NON-NLS-1$
 					true);
 			if (needNewLine)
 				addNewLine(view, args);
 			args.add(arg);
 			needNewLine = true;
 		}
-		
+
 		if (origArgv != null) {
 			// remove existing header arg if present
-			removeArgMatching(origArgv, "(?i)/H.*"); //$NON-NLS-1$
+			removeArgMatching(origArgv, "(?i)" + OPTION_CHARS + "H.*"); //$NON-NLS-1$
 			
 			// remove any /F entries: we don't update parameter files
-			removeArgMatching(origArgv, "(?i)/F.*"); //$NON-NLS-1$
+			removeArgMatching(origArgv, "(?i)" + OPTION_CHARS + "F.*"); //$NON-NLS-1$
 
-			// keep remaining arguments, except for files
+			// keep remaining arguments, except for files 
 			for (Iterator<String> iter = origArgv.iterator(); iter.hasNext();) {
 				String origArg = iter.next();
-				if (origArg.matches("(?i)/[a-bd-z].*")) { //$NON-NLS-1$
+				if (origArg.matches("(?i)" + OPTION_CHARS + "[a-bd-z].*")) { //$NON-NLS-1$
 					args.add(origArg);
 					iter.remove();
 				}
@@ -339,7 +348,7 @@
 					explicitMaskPath ? 0 : maskDepth);
 			if (imageFormat == null || !format.equals(imageFormat)) {
 				imageFormat = format;
-				args.add("/" + format.toString()); //$NON-NLS-1$
+				args.add(OUT_OPTION_CHAR + format.toString()); //$NON-NLS-1$
 			}
 			
 			// emit source file
@@ -354,7 +363,7 @@
 			// emit explicit mask path if needed
 			if (explicitMaskPath) {
 				file = fromProjectToMakefilePath(view, maskPath);
-				args.add("/" + maskDepth); //$NON-NLS-1$
+				args.add(OUT_OPTION_CHAR + "" + maskDepth); //$NON-NLS-1$
 				args.add(view.unexpandMacros(file.setDevice(null).toOSString(), false));
 			}
 		}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/mmp/MMPView.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/mmp/MMPView.java	Thu Dec 03 12:04:42 2009 -0600
@@ -147,7 +147,7 @@
 	 * @return
 	 */
 	static boolean isAbsoluteLikePath(IPath mmpPath) {
-		return (mmpPath.isAbsolute() 
+		return (isAbsolutePath(mmpPath)
 				|| (mmpPath.segmentCount() > 0 && mmpPath.segment(0).equals("+")));  //$NON-NLS-1$
 	}
 	
@@ -1143,7 +1143,7 @@
 			IPath basePath = mmpPath.removeFileExtension();
 			baseName = basePath.lastSegment();
 			
-			if (basePath.isAbsolute()) {
+			if (isAbsolutePath(basePath)) {
 				dirPath = basePath.removeLastSegments(1);
 			} else {
 				dirPath = defFileBase.append(basePath.removeLastSegments(1));
@@ -1176,7 +1176,8 @@
 		} else {
 			// replace any "/~/" sequences 
 			if (dirPath.segmentCount() > 0)
-				dirPath = new Path(dirPath.addTrailingSeparator().toString().replace("/~/", "/"+implDirectory+"/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				dirPath = new Path(dirPath.addTrailingSeparator().toPortableString()
+						.replace("/~/", "/"+implDirectory+"/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		}
 		
 		// version identifier overrides unicode
@@ -1191,9 +1192,9 @@
 		
 		IPath prjPath = null;
 		IPath tempPath = dirPath.append(baseName + "." + ext); //$NON-NLS-1$
-		if (!tempPath.isAbsolute()) {
+		if (!isAbsolutePath(tempPath)) {
 			prjPath = tempPath; //convertMMPToProject(EMMPPathContext.DEFFILE, tempPath);
-		} else if (mmpPath == null || !mmpPath.isAbsolute()) {
+		} else if (mmpPath == null || !isAbsolutePath(mmpPath)) {
 			/*
 			IPath wsPath = epocHelper.convertFilesystemToWorkspace(tempPath);
 			if (wsPath != null)
@@ -1249,7 +1250,7 @@
 		if (realPath == null)
 			return null;
 
-		if (!realPath.isAbsolute()) {
+		if (!isAbsolutePath(realPath)) {
 			//realPath = ((IModel)mmpView.getModel()).getPath().removeLastSegments(1).append(realPath);
 			realPath = convertProjectToModelPath(realPath);
 		}
@@ -1280,7 +1281,7 @@
 
 		// return string value, containing literal .\ if not generic name
 		String mmpPath = pathString(dirPath.append(baseName + "." + ext)); //$NON-NLS-1$
-		if (isFixedDirectory && !dirPath.isAbsolute() && dirPath.segmentCount() == 0)
+		if (isFixedDirectory && !isAbsolutePath(dirPath) && dirPath.segmentCount() == 0)
 			mmpPath = "." + pathSeparator() + mmpPath; //$NON-NLS-1$
 		return mmpPath;
 	}
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/mmp/ResourceBlockListConverter.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/model/mmp/ResourceBlockListConverter.java	Thu Dec 03 12:04:42 2009 -0600
@@ -109,7 +109,8 @@
 				resource.setTargetFile(((IASTMMPSingleArgumentStatement) stmt).getArgument().getValue());
 			}
 			else if (EMMPStatement.TARGETPATH.matches(stmt)) {
-				resource.setTargetPath(new Path(((IASTMMPSingleArgumentStatement) stmt).getArgument().getValue()));
+				resource.setTargetPath(new Path(
+						HostOS.convertPathToUnix(((IASTMMPSingleArgumentStatement) stmt).getArgument().getValue())));
 			}
 			else if (EMMPStatement.HEADER.matches(stmt)) {
 				resource.setHeaderFlags(EGeneratedHeaderFlags.Header);
--- a/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/preprocessor/ASTPreprocessor.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.epoc.engine/src/com/nokia/carbide/internal/cpp/epoc/engine/preprocessor/ASTPreprocessor.java	Thu Dec 03 12:04:42 2009 -0600
@@ -690,7 +690,7 @@
 			*/
 			return null;
 		}
-		return new Pair(isUser, fileName);
+		return new Pair<Boolean, String>(isUser, fileName);
 		
 	}
 	
--- a/project/com.nokia.carbide.cpp.project.core/src/com/nokia/carbide/cpp/internal/project/core/updater/ProjectUpdater.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.project.core/src/com/nokia/carbide/cpp/internal/project/core/updater/ProjectUpdater.java	Thu Dec 03 12:04:42 2009 -0600
@@ -285,7 +285,7 @@
 	private static final String DEFAULT_PRJ_PLATFORM_COMMENT = Messages.getString("ProjectUpdater.PlatformsNotAvailableWithAllSDKsComment"); //$NON-NLS-1$
 
 	private static final String CUR_DIR = "."; //$NON-NLS-1$
-	private static final String EPOC32_INC = "\\epoc32\\include"; //$NON-NLS-1$
+	private static final String EPOC32_INC = File.separator +"epoc32" + File.separator + "include"; //$NON-NLS-1$ //$NON-NLS-2$
 	
 	private static final String[] IMPLICIT_LIB_PREFIXES = {
 		"dfpaeabi", //$NON-NLS-1$
@@ -1665,15 +1665,15 @@
 				"\r\n" +  //$NON-NLS-1$
 				"\r\n" +  //$NON-NLS-1$
 				"ifeq (WINS,$(findstring WINS, $(PLATFORM)))\r\n" +  //$NON-NLS-1$
-				"ZDIR=$(EPOCROOT)epoc32\\release\\$(PLATFORM)\\$(CFG)\\Z\r\n" +  //$NON-NLS-1$
+				"ZDIR=$(EPOCROOT)epoc32/release/$(PLATFORM)/$(CFG)/Z\r\n" +  //$NON-NLS-1$
 				"else\r\n" +  //$NON-NLS-1$
-				"ZDIR=$(EPOCROOT)epoc32\\data\\z\r\n" +  //$NON-NLS-1$
+				"ZDIR=$(EPOCROOT)epoc32/data/z\r\n" +  //$NON-NLS-1$
 				"endif\r\n" +  //$NON-NLS-1$
 				"\r\n" +  //$NON-NLS-1$
 				"\r\n" +  //$NON-NLS-1$
-				"TARGETDIR=$(ZDIR)\\resource\\apps\r\n" + //$NON-NLS-1$
+				"TARGETDIR=$(ZDIR)/resource/apps\r\n" + //$NON-NLS-1$
 				"\r\n" +  //$NON-NLS-1$
-				"ICONDIR=..\\gfx\r\n" +  //$NON-NLS-1$
+				"ICONDIR=../gfx\r\n" +  //$NON-NLS-1$
 				"\r\n" +  //$NON-NLS-1$
 				"do_nothing :\r\n" +  //$NON-NLS-1$
 				"\t@rem do_nothing\r\n" +  //$NON-NLS-1$
@@ -1696,8 +1696,8 @@
 				"#\r\n" +  //$NON-NLS-1$
 				"# NOTE 2: Usually, source paths should not be included in the bitmap\r\n" +  //$NON-NLS-1$
 				"# definitions. MifConv searches for the icons in all icon directories in a\r\n" +  //$NON-NLS-1$
-				"# predefined order, which is currently \\s60\\icons, \\s60\\bitmaps2.\r\n" +  //$NON-NLS-1$
-				"# The directory \\s60\\icons is included in the search only if the feature flag\r\n" +  //$NON-NLS-1$
+				"# predefined order, which is currently /s60/icons, /s60/bitmaps2.\r\n" +  //$NON-NLS-1$
+				"# The directory /s60/icons is included in the search only if the feature flag\r\n" +  //$NON-NLS-1$
 				"# __SCALABLE_ICONS is defined.\r\n" +  //$NON-NLS-1$
 				"# ----------------------------------------------------------------------------\r\n" +  //$NON-NLS-1$
 				"# NOTE: if you have JUSTINTIME enabled for your S60 3rd FP1 or newer SDK\r\n"+  //$NON-NLS-1$
--- a/project/com.nokia.carbide.cpp.project.core/src/com/nokia/carbide/cpp/internal/project/core/updater/SymbianBuildParser.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.project.core/src/com/nokia/carbide/cpp/internal/project/core/updater/SymbianBuildParser.java	Thu Dec 03 12:04:42 2009 -0600
@@ -40,7 +40,7 @@
 
 public class SymbianBuildParser {
 	
-	private static final String RESOURCE_APPS = "resource\\apps"; //$NON-NLS-1$
+	private static final String RESOURCE_APPS = "resource" + File.separator + "apps"; //$NON-NLS-1$
 	private static final String CDTBUILD_FILENAME = ".cdtbuild"; //$NON-NLS-1$
 	private static final String OPTION = "option"; //$NON-NLS-1$
 	private static final String TOOL = "tool"; //$NON-NLS-1$
@@ -180,7 +180,7 @@
 			public String convert(String value) {
 				String pathString = TextUtils.unquote(value, '"');
 				if (pathString.startsWith(EPOCROOT_VAR)) {
-					pathString = "\\" + pathString.substring(EPOCROOT_VAR.length()); //$NON-NLS-1$
+					pathString = File.separator + pathString.substring(EPOCROOT_VAR.length()); //$NON-NLS-1$
 					return pathString;
 				}
 				else if (!VARIABLE_PATTERN.matcher(pathString).matches()) // no other variables
--- a/project/com.nokia.carbide.cpp.project.ui/src/com/nokia/carbide/cpp/internal/project/ui/sharedui/BuilderSelectionComposite.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.project.ui/src/com/nokia/carbide/cpp/internal/project/ui/sharedui/BuilderSelectionComposite.java	Thu Dec 03 12:04:42 2009 -0600
@@ -112,4 +112,8 @@
     public boolean useSBSv2Builder() {
     	return useSBSv2Builder;
     }
+    
+    public void setUseSBSv2Builder(boolean useSBSv2Builder) {
+		this.useSBSv2Builder = useSBSv2Builder;
+	}
 }
--- a/project/com.nokia.carbide.cpp.project.ui/src/com/nokia/carbide/cpp/project/ui/sharedui/NewProjectPage.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/project/com.nokia.carbide.cpp.project.ui/src/com/nokia/carbide/cpp/project/ui/sharedui/NewProjectPage.java	Thu Dec 03 12:04:42 2009 -0600
@@ -22,6 +22,7 @@
 import com.nokia.carbide.cpp.internal.project.ui.sharedui.BuilderSelectionComposite;
 import com.nokia.carbide.internal.api.templatewizard.ui.IWizardDataPage;
 import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.HostOS;
 import com.nokia.cpp.internal.api.utils.core.TextUtils;
 
 import org.eclipse.core.resources.IProject;
@@ -45,7 +46,8 @@
 
     private Map<String, Object> data;
 	private Collection<IProject> projectCache;
-	private static boolean WINDOWS = File.separatorChar == '\\';
+	
+	/** composite displayed when SBSv1 and SBSv2 are both available */
 	private BuilderSelectionComposite builderComposite;
 	
 	public NewProjectPage(String title, String description) {
@@ -73,6 +75,10 @@
 		
 		if (builderComposite != null) {
 			data.put(USE_SBSV2_BUILDER, new Boolean(builderComposite.useSBSv2Builder()));
+		} else if (!SBSv2Utils.enableSBSv1Support()) {
+			data.put(USE_SBSV2_BUILDER, Boolean.TRUE);
+		} else if (!SBSv2Utils.enableSBSv2Support()) {
+			data.put(USE_SBSV2_BUILDER, Boolean.FALSE);
 		}
 		
 		return data;
@@ -113,7 +119,7 @@
 					new Object[] { getLocationPath().toString() } ));
 			return false;
 		}
-        if (WINDOWS && !validateDeviceExists()) {
+        if (HostOS.IS_WIN32 && !validateDeviceExists()) {
 			setErrorMessage(Messages.getString("NewProjectPage.InvalidDriveError")); //$NON-NLS-1$
 			return false;
         }
@@ -129,7 +135,7 @@
         }
         setErrorMessage(null);
         boolean valid = super.validatePage();
-        if (WINDOWS) {
+        if (HostOS.IS_WIN32) {
 	        if (locationGettingLong(projectName)) {
 	        	setMessage(Messages.getString("NewProjectPage.ExcessivelyLongPathError"), WARNING); //$NON-NLS-1$
 	        	return valid;
@@ -218,7 +224,8 @@
 	public void createControl(Composite parent) {
 		super.createControl(parent);
 
-		if (SBSv2Utils.enableSBSv2Support()) {
+		// if there is a choice to be made...
+		if (SBSv2Utils.enableSBSv1Support() && SBSv2Utils.enableSBSv2Support()) {
 			Control control = getControl();
 			if (control instanceof Composite) {
 				builderComposite = new BuilderSelectionComposite((Composite)control);
--- a/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-PlatsecApp/data/baseName_reg.rss	Wed Dec 02 09:52:39 2009 -0600
+++ b/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-PlatsecApp/data/baseName_reg.rss	Thu Dec 03 12:04:42 2009 -0600
@@ -10,7 +10,7 @@
 #include "$(baseName).hrh"
 #include "$(baseName).rls"
 #include <appinfo.rh>
-#include <$(baseName)_$(uid3).rsg>
+#include <$(baseName$lower)_$(uid3).rsg>
 
 UID2 KUidAppRegistrationResourceFile
 UID3 _UID3
--- a/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-PlatsecApp/src/baseNameAppUi.cpp	Wed Dec 02 09:52:39 2009 -0600
+++ b/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-PlatsecApp/src/baseNameAppUi.cpp	Thu Dec 03 12:04:42 2009 -0600
@@ -16,7 +16,7 @@
 #include <s32file.h>
 #include <hlplch.h>
 
-#include <$(baseName)_$(uid3).rsg>
+#include <$(baseName$lower)_$(uid3).rsg>
 
 #ifdef _HELP_AVAILABLE_
 #include "$(baseName)_$(uid3).hlp.hrh"
--- a/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-TouchUIApplication/data/baseName_reg.rss	Wed Dec 02 09:52:39 2009 -0600
+++ b/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-TouchUIApplication/data/baseName_reg.rss	Thu Dec 03 12:04:42 2009 -0600
@@ -10,7 +10,7 @@
 #include "$(baseName).hrh"
 #include "$(baseName).rls"
 #include <appinfo.rh>
-#include <$(baseName)_$(uid3).rsg>
+#include <$(baseName$lower)_$(uid3).rsg>
 
 UID2 KUidAppRegistrationResourceFile
 UID3 _UID3
--- a/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-TouchUIApplication/src/baseNameAppUi.cpp	Wed Dec 02 09:52:39 2009 -0600
+++ b/templates/com.nokia.carbide.cpp.templates/templates/projecttemplates/S60-TouchUIApplication/src/baseNameAppUi.cpp	Thu Dec 03 12:04:42 2009 -0600
@@ -16,7 +16,7 @@
 #include <s32file.h>
 #include <hlplch.h>
 
-#include <$(baseName)_$(uid3).rsg>
+#include <$(baseName$lower)_$(uid3).rsg>
 
 #ifdef _HELP_AVAILABLE_
 #include "$(baseName)_$(uid3).hlp.hrh"
--- a/uidesigner/com.nokia.carbide.cpp.uiq.ui/src/com/nokia/carbide/cpp/uiq/ui/viewwizard/ViewWizardManager.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/uidesigner/com.nokia.carbide.cpp.uiq.ui/src/com/nokia/carbide/cpp/uiq/ui/viewwizard/ViewWizardManager.java	Thu Dec 03 12:04:42 2009 -0600
@@ -389,7 +389,7 @@
 		Check.checkState(template != null);
 		String appUID = (String) template.getTemplateValues().get("uid3"); //$NON-NLS-1$
 		Check.checkState(appUID != null);
-		return appUID;
+		return appUID.toLowerCase();
 	}
 
 	private void createViewModelFromWizardData(Language language) throws Exception {
--- a/uidesigner/com.nokia.sdt.series60.componentlibrary/src/com/nokia/sdt/series60/viewwizard/ViewWizardManager.java	Wed Dec 02 09:52:39 2009 -0600
+++ b/uidesigner/com.nokia.sdt.series60.componentlibrary/src/com/nokia/sdt/series60/viewwizard/ViewWizardManager.java	Thu Dec 03 12:04:42 2009 -0600
@@ -348,7 +348,7 @@
 		Check.checkState(template != null);
 		String appUID = (String) template.getTemplateValues().get("uid3"); //$NON-NLS-1$
 		Check.checkState(appUID != null);
-		return appUID;
+		return appUID.toLowerCase();
 	}
 
 	private void createViewModelFromWizardData(Language language) throws Exception {