Added sf\3tshell platform with support for building beagle textshell+fshell ROMs.
authorTom Sutcliffe <thomas.sutcliffe@accenture.com>
Sat, 28 Aug 2010 00:12:38 +0100
changeset 42 e81b4e28b3e2
parent 41 4a2ffd3562a3
child 43 96bfe2624d23
child 44 a83fed0e0b9a
child 47 1c9b53dbf08b
Added sf\3tshell platform with support for building beagle textshell+fshell ROMs. As part of that: * Added baserom command and tweaked it to be more friendly with SF baselines. * Lots of build fixes Also cd now makes sure the current working directory matches the file system with respect to case.
build/common/bld.inf
build/common/fsh_makesis_defs.iby
build/common/fsh_manifest_defs.iby
build/common/fsh_rombuild_defs.iby
build/common/fshell.iby
build/sf/3tshell/bld.inf
build/sf/3tshell/fshell_platform.iby
build/sf/3tshell/platform.mmh
build/sf/bld_shared.inf
build/sf/platform_shared.mmh
core/group/fshell_core.iby
core/src/commands.cpp
core/src/fshell.cpp
core/src/fshell.mmp
documentation/change_history.pod
libraries/iosrv/bwins/iocliu.def
libraries/iosrv/client/file_utils.cpp
libraries/iosrv/eabi/iocliu.def
libraries/iosrv/inc/ioutils.h
plugins/consoles/vt100cons/group/vt100debugport.mmp
tools/baserom
tools/baserom.bat
tools/fsh-builddocs
tools/fsh-buildsis
--- a/build/common/bld.inf	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/common/bld.inf	Sat Aug 28 00:12:38 2010 +0100
@@ -45,6 +45,8 @@
 ..\..\tools\createsrc		\epoc32\tools\createsrc
 ..\..\tools\createsrc.bat	\epoc32\tools\createsrc.bat
 ..\..\tools\exportall		\epoc32\tools\exportall
+..\..\tools\baserom			\epoc32\tools\baserom
+..\..\tools\baserom.bat		\epoc32\tools\baserom.bat
 
 PRJ_MMPFILES
 
--- a/build/common/fsh_makesis_defs.iby	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/common/fsh_makesis_defs.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -25,6 +25,7 @@
 #define ABI_DIR \epoc32\release\ ## ABI
 #define ABI_FOR(file) ABI_DIR ## \file
 
+#define DATAZ_ \epoc32\data\z
 #define ZPRIVATE \epoc32\data\z\private
 #define ZSYSTEM \epoc32\data\z\system
 #define ZRESOURCE \epoc32\data\z\resource
@@ -39,6 +40,7 @@
 #define FSHELL_DEBUG_EXECUTABLE_FILE(fileName) FSHELL_EXECUTABLE_FILE_ABI(fileName, ABI_FOR(udeb\ ## fileName))
 #define FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) FSHELL_EXECUTABLE_FILE_ABI(fileNameTo, ABI_FOR(urel\ ## fileNameFrom))
 #define FSHELL_RENAMED_DEBUG_EXECUTABLE_FILE(fileNameFrom, fileNameTo) FSHELL_EXECUTABLE_FILE_ABI(fileNameTo, ABI_FOR(udeb\ ## fileNameFrom))
+#define FSHELL_EXECUTABLE_AS_DATA(fileNameFrom, fileNameTo) FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo)
 #define FSHELL_KERNEL_EXTENSION(fileName) FSHELL_EXECUTABLE_FILE(fileName)
 #define FSHELL_DEBUG_KERNEL_EXTENSION(fileName) FSHELL_DEBUG_EXECUTABLE_FILE(fileName)
 #define FSHELL_DEVICE_DRIVER(fileName) FSHELL_EXECUTABLE_FILE(fileName)
--- a/build/common/fsh_manifest_defs.iby	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/common/fsh_manifest_defs.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -39,6 +39,7 @@
 #define FSHELL_DEBUG_EXECUTABLE_FILE(fileName) FSHELL_EXECUTABLE_FILE_ABI(ABI_FOR(udeb\ ## fileName))
 #define FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) FSHELL_EXECUTABLE_FILE_ABI(ABI_FOR(urel\ ## fileNameFrom))
 #define FSHELL_RENAMED_DEBUG_EXECUTABLE_FILE(fileNameFrom, fileNameTo) FSHELL_EXECUTABLE_FILE_ABI(ABI_FOR(udeb\ ## fileNameFrom))
+#define FSHELL_EXECUTABLE_AS_DATA(fileNameFrom, fileNameTo) FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo)
 #define FSHELL_KERNEL_EXTENSION(fileName) FSHELL_EXECUTABLE_FILE(fileName)
 #define FSHELL_DEBUG_KERNEL_EXTENSION(fileName) FSHELL_DEBUG_EXECUTABLE_FILE(fileName)
 #define FSHELL_DEVICE_DRIVER(fileName) FSHELL_EXECUTABLE_FILE(fileName)
--- a/build/common/fsh_rombuild_defs.iby	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/common/fsh_rombuild_defs.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -22,6 +22,7 @@
 
 #define FSHELL_DATA_FILE(fileNameFrom, fileNameTo) data=##fileNameFrom fileNameTo
 #define FSHELL_EXECUTABLE_FILE(fileName) file=\epoc32\release\##MAIN##\##BUILD##\##fileName sys\bin\##fileName
+#define FSHELL_EXECUTABLE_AS_DATA(fileNameFrom, fileNameTo) data=\epoc32\release\##MAIN##\##BUILD##\fileNameFrom sys\bin\fileNameTo
 #define FSHELL_DEBUG_EXECUTABLE_FILE(fileName) file=\epoc32\release\##MAIN##\##BUILD##\##fileName sys\bin\##fileName
 #define FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) file=\epoc32\release\##MAIN##\##BUILD##\##fileNameFrom sys\bin\##fileNameTo
 #define FSHELL_DEBUG_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) file=\epoc32\release\##MAIN##\##BUILD##\##fileNameFrom sys\bin\##fileNameTo
@@ -45,6 +46,7 @@
 
 #define FSHELL_DATA_FILE(fileNameFrom, fileNameTo) data=##fileNameFrom fileNameTo
 #define FSHELL_EXECUTABLE_FILE(fileName) file=##ABI_DIR##\##DEBUG_DIR##\##fileName sys\bin\##fileName
+#define FSHELL_EXECUTABLE_AS_DATA(fileNameFrom, fileNameTo) file=##ABI_DIR##\##DEBUG_DIR##\fileNameFrom sys\bin\fileNameTo
 #define FSHELL_DEBUG_EXECUTABLE_FILE(fileName) file=##ABI_DIR##\##DEBUG_DIR##\##fileName sys\bin\##fileName
 #define FSHELL_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) file=##ABI_DIR##\##BUILD_DIR\##fileNameFrom sys\bin\##fileNameTo
 #define FSHELL_DEBUG_RENAMED_EXECUTABLE_FILE(fileNameFrom, fileNameTo) file=##ABI_DIR##\##DEBUG_DIR\##fileNameFrom sys\bin\##fileNameTo
--- a/build/common/fshell.iby	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/common/fshell.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -43,5 +43,6 @@
 #include <guicons.iby>
 #include <defcons.iby>
 #include <consoleproxy.iby>
+FSHELL_EXECUTABLE_FILE(consoleextensions.dll) // TODO move this to the new fshell_consoles.iby
 
 #endif // FSHELL_IBY
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/sf/3tshell/bld.inf	Sat Aug 28 00:12:38 2010 +0100
@@ -0,0 +1,24 @@
+// bld.inf
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+// The macroing here is a little messy to get things included in the right order...
+#define FSHELL_PLATFORM_SHARED_MMH
+#include "platform.mmh"
+#undef FSHELL_PLATFORM_SHARED_MMH
+#include "../platform_shared.mmh"
+#define PLATFORM_IBY_EXPORTED
+#include "../bld_shared.inf"
+
+PRJ_EXPORTS
+.\platform.mmh       \epoc32\include\fshell\platform.mmh
+FSHELL_ROM_INCLUDE2(platform.mmh, fshell\platform.mmh)
+FSHELL_ROM_INCLUDE(fshell_platform.iby)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/sf/3tshell/fshell_platform.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -0,0 +1,51 @@
+// fshell_platform.iby
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#ifndef FSHELL_PLATFORM_IBY
+#define FSHELL_PLATFORM_IBY
+
+#ifdef FSHELL_MAKESIS
+
+:"Accenture"
+%{"Accenture"}
+
+HASH{"fshell (SF)"},(FSHELL_UID_SIS),FSHELL_VERSION,0,FSHELL_TIMESTAMP,TYPE=SA
+
+#else
+
+// The minimum that fshell requires to rombuild successfully
+
+// Don't ask me...
+#undef SYMBIAN_BAFL_SYSUTIL
+#undef SYMBIAN_BAFL_ACTIVITYMGR
+//#undef SYMBIAN_CENREPNOTIFIERHANDLER
+
+
+//device[VARID]=ABI_DIR\BUILD_DIR\_beagle_euart.pdd sys\bin\euart.pdd
+//device[VARID]=ABI_DIR\BUILD_DIR\ECOMM.LDD \sys\bin\ecomm.ldd
+
+
+// Minimum dependancies
+#define __CENTRALREPOSITORY_IBY__
+#define BTRACE_INCLUDED
+#include <ecom.iby>
+#include <store.iby>
+#include <bafl.iby>
+#include <charconv.iby>
+file=ABI_DIR\BUILD_DIR\featmgr.dll		sys\bin\featmgr.dll
+file=ABI_DIR\BUILD_DIR\abclient.dll		sys\bin\abclient.dll
+file=ABI_DIR\BUILD_DIR\centralrepository.dll sys\bin\centralrepository.dll
+#include <dbms.iby>
+
+#endif
+
+#endif // FSHELL_PLATFORM_IBY
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/sf/3tshell/platform.mmh	Sat Aug 28 00:12:38 2010 +0100
@@ -0,0 +1,36 @@
+// platform.mmh
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#ifndef FSHELL_PLATFORM_MMH
+#define FSHELL_PLATFORM_MMH
+
+#define FSHELL_PLATFORM_FOUNDATION 3
+
+#ifndef FSHELL_PLATFORM_SHARED_MMH
+#include <fshell/platform_shared.mmh>
+#endif
+
+#define FSHELL_AUTOSTART
+
+#define FSHELL_BASE_ROM
+#define FSHELL_NO_COMMS_SUPPORT
+#define FSHELL_NO_TELEPHONY_SUPPORT
+#define FSHELL_NO_APPARC_SUPPORT
+#define FSHELL_NO_EZLIB_SUPPORT
+#define FSHELL_NO_WSERV_SUPPORT
+#define FSHELL_NO_AUDIO_SUPPORT
+#define FSHELL_NO_LBS_SUPPORT
+#define FSHELL_NO_SQL_SUPPORT
+#define FSHELL_NO_PIPS_SUPPORT
+#define FSHELL_NO_SPCRE_SUPPORT
+#define FSHELL_NO_CRYPTO_SUPPORT
+
+#endif
--- a/build/sf/bld_shared.inf	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/sf/bld_shared.inf	Sat Aug 28 00:12:38 2010 +0100
@@ -21,7 +21,10 @@
 PRJ_EXPORTS
 .\platform_shared.mmh       \epoc32\include\fshell\platform_shared.mmh
 FSHELL_ROM_INCLUDE2(platform_shared.mmh, fshell\platform_shared.mmh)
+
+#ifndef PLATFORM_IBY_EXPORTED
 FSHELL_ROM_INCLUDE(fshell_platform.iby)
+#endif
 
 PRJ_MMPFILES
 gnumakefile    ..\common\fsh_buildsis.mk
--- a/build/sf/platform_shared.mmh	Thu Aug 26 15:28:08 2010 +0100
+++ b/build/sf/platform_shared.mmh	Sat Aug 28 00:12:38 2010 +0100
@@ -29,7 +29,7 @@
 #define FSHELL_CORE_SUPPORT_SERIAL_ICON "port=COMM::1, rate=115200"
 #endif
 
-#define FSHELL_NO_SAMPLINGPROFILER_SUPPORT
+//#define FSHELL_NO_SAMPLINGPROFILER_SUPPORT
 #define FSHELL_NO_EGL_SUPPORT // The lib exists but not the dll itself...
 #define FSHELL_NO_OPENVG_SUPPORT // ditto
 
--- a/core/group/fshell_core.iby	Thu Aug 26 15:28:08 2010 +0100
+++ b/core/group/fshell_core.iby	Sat Aug 28 00:12:38 2010 +0100
@@ -170,12 +170,15 @@
 #endif
 
 #ifdef FSHELL_REPLACE_ECONS
-FSHELL_RENAMED_EXECUTABLE_FILE(iocons.dll, econs.dll)
+//FSHELL_RENAMED_EXECUTABLE_FILE(iocons.dll, econs.dll)
+// New method that doesn't involve removing other occurences of econs.dll from your IBYs. See TODO
+FSHELL_EXECUTABLE_AS_DATA(iocons.dll, iocons.dll)
 
 #ifdef FSHELL_USE_BLUETOOTH_CONSOLE
 FSHELL_DATA_FILE(ZSYSTEM\console\iosrv.ini.bluetooth, system\console\iosrv.ini)
 #else
-FSHELL_DATA_FILE(ZSYSTEM\console\iosrv.ini.econs_fb, system\console\iosrv.ini)
+//TomS: I don't think this should be here any more - the VT100 consoles don't need it and I get by quite happily without it
+//FSHELL_DATA_FILE(ZSYSTEM\console\iosrv.ini.econs_fb, system\console\iosrv.ini)
 #ifdef FSHELL_WSERV_SUPPORT
 FSHELL_RENAMED_EXECUTABLE_FILE(econseik.dll, econs_fb.dll)
 #else
--- a/core/src/commands.cpp	Thu Aug 26 15:28:08 2010 +0100
+++ b/core/src/commands.cpp	Sat Aug 28 00:12:38 2010 +0100
@@ -356,6 +356,7 @@
 		}
 	else
 		{
+		iDir.Normalize(FsL());
 		LeaveIfFileNotFound(iDir);
 		if (!iDir.IsDirL(FsL()))
 			{
--- a/core/src/fshell.cpp	Thu Aug 26 15:28:08 2010 +0100
+++ b/core/src/fshell.cpp	Sat Aug 28 00:12:38 2010 +0100
@@ -389,6 +389,45 @@
 	// Possibly this isn't the best place to put it...
 	RMemoryAccess::LoadDriver();
 #endif
+
+#ifdef FSHELL_CAP_ALL // If we don't have all caps we can't hack around with sys\bin directory
+	// See if we were built/installed with FSHELL_REPLACE_ECONS and if so, do just that.
+	// A bit inefficient we do it every time, but can't see a better way
+	// The benefit of doing it like this is that it doesn't require us to remove other occurences of econs.dll (like econseik.dll) from the rombuild
+	RLibrary iocons;
+	TInt err = iocons.Load(_L("iocons.dll"));
+	if (err == KErrNone)
+		{
+		// We don't include iocons.dll unless FSHELL_REPLACE_ECONS was specified at buildrom time
+		CleanupClosePushL(iocons);
+		RFs fs;
+		CleanupClosePushL(fs);
+		User::LeaveIfError(fs.Connect());
+		_LIT(KPath, "%c:\\sys\\bin\\econs.dll");
+		TBuf<32> econsPath;
+		TChar systemDrive = 'c';
+		fs.DriveToChar(fs.GetSystemDrive(), systemDrive);
+		econsPath.Format(KPath, TUint(systemDrive));
+		TEntry ioconsEntry;
+		err = fs.Entry(iocons.FileName(), ioconsEntry);
+		if (err == KErrNone)
+			{
+			TEntry econsEntry;
+			if (fs.Entry(econsPath, econsEntry) == KErrNone && econsEntry.iSize == ioconsEntry.iSize)
+				{
+				// Then we've already copied iocons.dll to econs.dll, don't do it again
+				}
+			else
+				{
+				CFileMan* fm = CFileMan::NewL(fs);
+				fm->Copy(iocons.FileName(), econsPath, CFileMan::ERecurse | CFileMan::EOverWrite);
+				// Ignore the error - if it fails it shouldn't prevent fshell starting up
+				delete fm;
+				}
+			}
+		CleanupStack::PopAndDestroy(2, &iocons); // fs, iocons
+		}
+#endif
 	}
 
 void CShell::PrintPrompt()
--- a/core/src/fshell.mmp	Thu Aug 26 15:28:08 2010 +0100
+++ b/core/src/fshell.mmp	Sat Aug 28 00:12:38 2010 +0100
@@ -86,6 +86,8 @@
 #define PLAT platform_ARM4
 #elif defined(MARM_ARMV5)
 #define PLAT platform_ARMV5
+#else
+#error "Platform not understood in fshell.mmp!"
 #endif
 
 #ifdef SBSV2
--- a/documentation/change_history.pod	Thu Aug 26 15:28:08 2010 +0100
+++ b/documentation/change_history.pod	Sat Aug 28 00:12:38 2010 +0100
@@ -42,6 +42,10 @@
 
 Added C<ENotifyKeypresses> and C<ECaptureCtrlC> flags to CCommandBase, so commands can get keypresses and handle ctrl-C via callbacks instead of having to implement custom active objects. As part of this extended the CCommandBase extension interface to MCommandExtensionsV2 for the new virtual functions KeyPressed(TUint aKeyCode, TUint aModifiers) and CtrlCPressed(). sudo now cleans up correctly by using ECaptureCtrlC.
 
+=item *
+
+fshell's current working directory is now normalised (via new TFileName2::Normalize function) so that the case matches what's on the filesystem).
+
 =head2 Release 000.2-000.5
 
 Test releases with build fixes.
--- a/libraries/iosrv/bwins/iocliu.def	Thu Aug 26 15:28:08 2010 +0100
+++ b/libraries/iosrv/bwins/iocliu.def	Sat Aug 28 00:12:38 2010 +0100
@@ -549,4 +549,5 @@
 	?ExtensionVersion@MCommandExtensionsV2@IoUtils@@UBE?AW4TCommandExtensionVersion@2@XZ @ 548 NONAME ; enum IoUtils::TCommandExtensionVersion IoUtils::MCommandExtensionsV2::ExtensionVersion(void) const
 	?KeyPressed@MCommandExtensionsV2@IoUtils@@UAEXII@Z @ 549 NONAME ; void IoUtils::MCommandExtensionsV2::KeyPressed(unsigned int, unsigned int)
 	?ReadKey@CCommandBase@IoUtils@@QAEIXZ @ 550 NONAME ; unsigned int IoUtils::CCommandBase::ReadKey(void)
+	?Normalize@TFileName2@IoUtils@@QAEXAAVRFs@@@Z @ 551 NONAME ; void IoUtils::TFileName2::Normalize(class RFs &)
 
--- a/libraries/iosrv/client/file_utils.cpp	Thu Aug 26 15:28:08 2010 +0100
+++ b/libraries/iosrv/client/file_utils.cpp	Sat Aug 28 00:12:38 2010 +0100
@@ -511,3 +511,22 @@
 	User::LeaveIfError(FindFile(aFs));
 	}
 
+EXPORT_C void TFileName2::Normalize(RFs& aFs)
+	{
+	// Change this so that the case of each component matches what the file system reckons. ie C:\SYS\Bin would be changed to c:\sys\bin
+	ASSERT(IsAbsolute());
+	TInt err = KErrNone;
+	TEntry entry;
+	TParse parse;
+	parse.Set(*this, NULL, NULL);
+
+	while (!err)
+		{
+		err = aFs.Entry(parse.FullName(), entry);
+		if (!err) err = parse.PopDir();
+		if (!err)
+			{
+			Replace(parse.FullName().Length(), entry.iName.Length(), entry.iName);
+			}
+		}
+	}
--- a/libraries/iosrv/eabi/iocliu.def	Thu Aug 26 15:28:08 2010 +0100
+++ b/libraries/iosrv/eabi/iocliu.def	Sat Aug 28 00:12:38 2010 +0100
@@ -625,4 +625,5 @@
 	_ZNK7IoUtils20MCommandExtensionsV216ExtensionVersionEv @ 624 NONAME
 	_ZTIN7IoUtils20MCommandExtensionsV2E @ 625 NONAME
 	_ZTVN7IoUtils20MCommandExtensionsV2E @ 626 NONAME
+	_ZN7IoUtils10TFileName29NormalizeER3RFs @ 627 NONAME
 
--- a/libraries/iosrv/inc/ioutils.h	Thu Aug 26 15:28:08 2010 +0100
+++ b/libraries/iosrv/inc/ioutils.h	Sat Aug 28 00:12:38 2010 +0100
@@ -186,6 +186,7 @@
 	IMPORT_C void SetIsDirectoryL(); // Ensure the descriptor ends in a slash
 	IMPORT_C TInt FindFile(RFs& aFs);
 	IMPORT_C void FindFileL(RFs& aFs);
+	IMPORT_C void Normalize(RFs& aFs);
 private:
 	void CheckSpaceL(TInt aLengthToAdd) const;
 private:
--- a/plugins/consoles/vt100cons/group/vt100debugport.mmp	Thu Aug 26 15:28:08 2010 +0100
+++ b/plugins/consoles/vt100cons/group/vt100debugport.mmp	Sat Aug 28 00:12:38 2010 +0100
@@ -26,5 +26,6 @@
 library			euser.lib
 library			econs.lib
 library			vt100.lib
+library			consoleextensions.lib
 
 deffile			vt100cons.def
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/baserom	Sat Aug 28 00:12:38 2010 +0100
@@ -0,0 +1,931 @@
+#!perl -w
+# baserom
+# 
+# Copyright (c) 2009 - 2010 Accenture. All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+# 
+# Initial Contributors:
+# Accenture - Initial contribution
+#
+use strict;
+use Cwd;
+use Getopt::Long;
+use File::Path;
+
+#fwd decls for functions.
+sub CreateNewObeyFile();
+sub ProcessCommandLine();
+sub Usage();
+sub ConvertIbyLine($);
+sub FindMissingDeps($);
+sub ResolveMissingDeps($);
+sub FindIby($);
+sub CheckIbyContains($$);
+sub headerInfo($);
+sub trim($);
+sub Query($$);
+sub makeFullFileName($);
+
+
+# globals
+my $verbose = 0;
+my $help;
+my $epocroot = $ENV{"epocroot"};
+my $tempDir = $ENV{"temp"};
+my $romIncludeDir;
+my $obyName;
+my $obyPath;
+my $baseObeyFile = "tshell.oby";
+my $main = "armv5";
+my $build = "udeb";
+my $variant = "h4hrp";
+my $extraInclude = undef;
+
+my %ignoreDeps = ('scppnwdl.dll' => 1, 'drtaeabi.dll' => 1, 'drtrvct2_2.dll' => 1, 'dfpaeabi.dll' => 1, 'dfprvct2_2.dll' => 1);
+
+ProcessCommandLine();
+
+my $newObyFile;
+my $missingCount;
+my $continue;
+do {
+  $continue = 0;
+  $newObyFile = CreateNewObeyFile();
+  my $missingFiles = FindMissingDeps($newObyFile);
+  $missingCount = scalar(@$missingFiles);
+  
+  if ($missingCount) {
+    #print "$missingCount missing dependancies:\n";
+    #foreach my $dep (@$missingFiles) {
+    #	if (defined $dep->[1]) {
+    #		print "$dep->[0] UID3: $dep->[1]\n";
+    #	} else {
+    #		print "$dep->[0]\n";
+    #	}
+    #}
+
+    if (Query("\nThere are $missingCount missing dependancies; resolve them now?", "yn")==0) {
+
+    	ResolveMissingDeps($missingFiles);
+    	
+    	$continue = 1;
+    	
+    } else {
+    	$newObyFile = CreateNewObeyFile();
+    }
+  }
+} while ($missingCount && $continue);
+
+print "New OBY file: $newObyFile\n\n";
+print "To build a ROM:\n";
+print "rom --type tshell_$obyName --inst $main --build $build --variant $variant\n";
+exit(0);
+
+
+sub ProcessCommandLine() {
+	Getopt::Long::Configure ("bundling");
+	GetOptions( 'h' => \$help, 
+	            'v+' => \$verbose, 
+	            'e=s' => \$epocroot, 
+	            'i=s' => \$romIncludeDir, 
+				'x=s' => \$extraInclude,
+	            'o=s' => \$baseObeyFile, 
+	            'V=s' => \$variant,
+	            't=s' => \$main,
+	            'b=s' => \$build);
+	Usage() if ($help);
+
+	$epocroot = "$epocroot\\" unless $epocroot =~ m/\\$/;
+	my ($drive) = (getcwd =~ m/^(\w)\:/);
+	die "Can't get current drive\n" unless $drive;
+	$epocroot = "$drive:$epocroot";
+	print "Using epocroot $epocroot\n" if ($verbose);
+
+
+
+	($romIncludeDir = "epoc32\\rom\\include") unless ($romIncludeDir);
+	$romIncludeDir =~ s/\\$//; # remove trailing \ if it exists
+	$romIncludeDir = "$epocroot$romIncludeDir";
+	print "Using include directory $romIncludeDir\n" if ($verbose);
+
+	unless (scalar (@ARGV) == 1) {
+		print "Inavlid arguments\n";
+		Usage();
+		}
+		
+	$obyPath = $ARGV[0];
+	if ($obyPath =~ m/.*[\\\/]([^.]+)\..*/i) {
+		$obyName = $1;
+	} else {
+		$obyName = $obyPath;
+	}
+	
+	die "ERROR: Build must be either 'udeb' or 'urel'\n" unless ($build =~ m/(udeb)|(urel)/i);
+	
+	print "Using variant $variant, build $main $build\n";
+}
+
+sub CreateNewObeyFile() {
+	unless (-d $obyName) {
+		mkdir $obyName or die "Can't create dir $obyName: $!\n";
+	}
+
+	open OBEY, "<$obyPath" or die "Can't open $obyPath: $!\n";
+
+
+	my %ibysProcessed;
+	my @ibyStack;
+	
+	my $obyBaseName;
+	if ($baseObeyFile =~ m/(.*)\.oby/i) {
+		$obyBaseName = $1;
+	} else {
+		$obyBaseName = "tshell";
+	}
+	
+	my $newObyName = "${obyBaseName}_$obyName.oby";
+
+	open TSHELL_OBY, "<$baseObeyFile" or die "Can't open $baseObeyFile: $!\n";
+	open TSHELL_NEW, ">$newObyName" or die "Can't write to $newObyName: $!\n";
+
+	print "Creating tshell_$obyName.oby\n";
+
+	while (my $line = <TSHELL_OBY>) {
+		print TSHELL_NEW "$line";
+	}
+
+	close (TSHELL_OBY);
+
+	while (my $line = <OBEY>) {
+		chomp $line;
+		if ($line =~ m/^#include\s+[<"](.*)[>"]/ ) {
+			my $iby = $1;
+			if (!$ibysProcessed{lc($iby)}) {
+				print "Adding $iby to stack\n" if ($verbose);
+				push @ibyStack, $iby;
+				$ibysProcessed{lc($iby)} = 1;
+				}
+			print TSHELL_NEW "#include \"$obyName\\$iby\"\n";
+			next;
+		} else {
+			print TSHELL_NEW ConvertIbyLine("$line");
+			print TSHELL_NEW "\n";
+		}
+	}
+
+	close TSHELL_NEW;
+
+	while (my $iby = pop(@ibyStack)) {
+		print "Processing $iby\n" if ($verbose);
+		my $fullIby = "$romIncludeDir\\$iby";
+		unless (-f $fullIby) {
+			warn "$fullIby does not exist\n" ;
+			next;
+		}
+		
+		my $fixedIby = $iby;
+		$fixedIby =~ s|^(\.\.[\\/])*||; # get rid of ..\ at path start
+		$fixedIby =~ s|^[\\/]||; # remove \ at start too
+		my ($ibyPath, $ibyFile) = ($fixedIby =~ m|^((?:.*[\\/])?)(.*)$|);
+		if (($ibyPath) && (!-d "$obyName\\$ibyPath")) {
+			$ibyPath =~ s|[\\/]$||;
+			mkpath("$obyName\\$ibyPath") or die "Can't create path $obyName\\$ibyPath: $!\n";
+			$ibyPath .= "/";
+		}
+		
+		my $newIby = "$obyName\\$ibyPath$ibyFile";
+		
+		#BEGIN TOMSCI
+		# For the purposes of finding #includes, we run $fulliby through CPP first so that we don't pick up includes that are #ifdef'd out
+		# To prevent the #includes being expanded, we have to change them in the file we run cpp over.
+		open IBY, "<$fullIby" or die "Can't open $fullIby: $!\n";		
+		open NOINCLUDEIBY, ">$newIby.noinclude" or die "Can't open $newIby.noinclude: $!\n";
+		while (my $line = <IBY>) {
+			$line =~ s/#include/BASEROMHASHINCLUDE/;
+			print NOINCLUDEIBY $line;
+		}
+		close IBY;
+		close NOINCLUDEIBY;
+		my $cppOpts = "-undef -traditional -lang-c++ -nostdinc -I . -I $romIncludeDir";
+		if ($extraInclude) {
+			if (!($newIby =~ /$extraInclude$/)) { # Make sure we don't include the extraInclude in itself
+				$cppOpts .= " -include $romIncludeDir\\$extraInclude";
+			}
+		}
+		
+		my $cmd .= "cpp $cppOpts $newIby.noinclude";
+		print "running: $cmd\n" if ($verbose);
+		open IBYCPP, "$cmd |" or die "Can't run '$cmd': $!\n";
+		while (my $line = <IBYCPP>) {
+			chomp $line;
+			#print "TOMSCI: $line\n";
+			if ($line =~ m/^BASEROMHASHINCLUDE\s+[<"](.*)[>"]/ ) {
+				my $iby = $1;
+				if (!$ibysProcessed{lc($iby)}) {
+					print "Adding $iby to stack\n" if ($verbose);
+					push @ibyStack, $iby;
+					$ibysProcessed{lc($iby)} = 1;
+				}
+			}
+		}
+		close IBYCPP;
+		#END TOMSCI
+
+		open IBY, "<$fullIby" or die "Can't open $fullIby: $!\n";		
+		open NEWIBY, ">$newIby" or die "Can't open $newIby: $!\n";
+		print "Creating $newIby\n" if ($verbose);
+		
+		while (my $line = <IBY>) {
+			chomp $line;
+			if ($line =~ m/^#include\s+[<"](.*)[>"]/ ) {
+				my $iby = $1;
+				#if (!$ibysProcessed{lc($iby)}) {
+				#	print "Adding $iby to stack\n" if ($verbose);
+				#	push @ibyStack, $iby;
+				#	$ibysProcessed{lc($iby)} = 1;
+				#	}
+				print NEWIBY "#include \"$iby\"\n";
+				next;
+			} else {
+				print NEWIBY ConvertIbyLine("$line");
+				print NEWIBY "\n";
+			}
+		}
+		
+		
+		close IBY;
+		close NEWIBY;
+	}
+	return $newObyName;
+}
+
+
+sub ConvertIbyLine($) {
+	my $line = shift;
+	
+	if ($line =~ m/^\s*\w*ECOM_PLUGIN(?:_UDEB)?\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)\s*$/ ) {
+		my $dll = $1;
+		my $rsc = $2;
+		
+		my ($dllName) = $dll =~ m/^(.*?)\./;
+		$rsc =~ s/[A-Fa-f0-9]{8}\.rs[cs]/$dllName.rsc/; # Some broken IBYs specify .rss instead of .rsc
+		
+		return "file=\\epoc32\\release\\##MAIN\\##BUILD##\\$dll\t\"sys\\bin\\$dll\"\n".
+				"data=\\epoc32\\data\\Z\\resource\\Plugins\\$rsc\t\"resource\\plugins\\$rsc\"";
+	}
+	
+	if ($line =~ m|\\ABI_DIR\\|) {
+		$line =~ s|\\ABI_DIR\\|\\epoc32\\release\\##MAIN##\\|;
+	} else {
+		$line =~ s|ABI_DIR\\|\\epoc32\\release\\##MAIN##\\|;
+	}
+	$line =~ s|\\BUILD_DIR\\|\\##BUILD##\\|;
+	$line =~ s|\\DEBUG_DIR\\|\\##BUILD##\\|;
+	$line =~ s|\\USB_DIR\\|\\##BUILD##\\|;
+	$line =~ s|ZRESOURCE\\|\\epoc32\\data\\Z\\resource\\|;
+	$line =~ s|ZPRIVATE\\|\\epoc32\\data\\Z\\private\\|;
+	$line =~ s|ZSYSTEM\\|\\epoc32\\data\\Z\\system\\|;
+	$line =~ s|DATAZ_\\|\\epoc32\\data\\Z\\|;
+	
+	if ($line =~ m|MULTI_LINGUIFY\s*\(\s*RSC\s+(.*?)\s+(.*?)\s*\)|) {
+		my $localRsc = $1;
+		my $romRsc = $2;
+		
+		my @resources = <$epocroot$localRsc.R*>;
+		
+		if (scalar(@resources)) {
+			$localRsc = $resources[0];
+			my $er = $epocroot;
+			$er =~ s/\\/\\\\/g;
+			$localRsc =~ s|$er|\\|;
+			#print "FOUND: $localRsc\n";
+		} else {
+			print "WARNING: resource for $romRsc could not be found\n";
+			$localRsc .= ".RSC";
+		}
+		
+		$line = "data=$localRsc\t\"$romRsc.RSC\"";
+	}
+	
+	if ($line =~ m|^#\s*include (["^])(.*?)([">])(.*)$|) {
+		my ($firstQuote, $include, $lastQuote, $extra) = ($1, $2, $3, $4);
+		$include =~ s|^(\.\.[\\/])*||;
+		$include =~ s|^[\\/]||;
+		$line = "#include $firstQuote$include$lastQuote$extra\n";
+	}
+	
+	return $line;
+}
+
+
+sub Usage() {
+	require Pod::Text;
+	print "\n";
+	my $parser = Pod::Text->new();
+	$parser->parse_from_file($0);
+	exit;
+}
+
+
+sub FindMissingDeps($) {
+	my $obyFile = shift;
+	print "Checking dependancies...\n";
+	
+	my $ibys = {};
+	my $filesByName = {};
+	my $filesByUid = {};
+	
+	
+	# since cpp doesn't deal with macros inside #include's, do it manually here:
+	print "Manually processing $obyFile\n" if ($verbose);
+	open IBY, "<$obyFile" or die "Can't open $obyFile: $!\n";
+	my $ibyFile = "$tempDir\\baserom.tmp";
+	open TEMPIBY, ">$ibyFile" or die "Can't open $ibyFile: $!\n";
+	
+	while (my $line = <IBY>) {
+		$line =~ s/\#\#VARIANT\#\#/$variant/;
+		$line =~ s/^\s*#/#/;
+		print TEMPIBY $line;
+	}
+	close IBY;
+	close TEMPIBY;
+	
+	my $cppOpts = "-undef -traditional -lang-c++ -nostdinc -I . -I ${epocroot}epoc32 -DVARIANT=$variant -DBUILD=$build -DMAIN=$main -DEUSERDIR=$main -DKMAIN=$main";
+	
+	my $cmd .= "cpp $cppOpts $ibyFile";
+	print "running: $cmd\n" if ($verbose);
+	
+	open CPP, "$cmd |" or die "Can't run '$cmd': $!\n";
+	while (my $line = <CPP>) {
+		chomp $line;
+		#print "\tCPP:$.:$line\n";
+		$line =~ s/EPOCROOT##/\\/;
+		$line =~ s/##//g;
+		
+		my $executableSrc = undef;
+		my $executableTrg = undef;
+
+		if ($line =~ m/^# 1 "(.*)" 1/) {
+			my $includedIby = $1;
+			print "iby included by cpp: $includedIby\n" if ($verbose);
+			$ibys->{lc($includedIby)} = 1;
+		} elsif ($line =~ m/^#/) {
+			# ignore - line inserted by c preprocessor
+			$line = "";
+		} elsif ($line =~ m/^\s*file\s*=\s*(.*?)\s+(.*)$/) {
+			$executableSrc = $1;
+			$executableTrg = trim $2;
+		} elsif ($line =~ m/^\s*(device|extension|primary|variant|file)\[0x[0-9A-Fa-f]{8}\]\s*=\s*(.*?)\s+(.*)$/) {
+			$executableSrc = $2;
+			$executableTrg = trim $3;
+		} elsif ($line =~ m|^\s*ECOM_PLUGIN\(\s*(.*?)\s*,| ) {
+			$executableSrc = $1;
+			$executableTrg = $executableSrc;
+		} elsif ($line =~ m|^\s*secondary\s*=(.*?)\s+(.*)$| ) {
+			$executableSrc = $1;
+			$executableTrg = trim $2;
+		} elsif ($line =~ m|^\s*data\s*=(.*?)\s|) {
+			my $data = $1;
+			print "WARNING: file $data not found\n" unless (-f "$epocroot$data");
+		} elsif (length(trim($line))==0) {
+			# ignore empty line
+		} elsif ($line =~ m|^\s*REM\s.*$|i) {
+			# comment, ignore.
+		} elsif ($line =~ m|^\s*patchdata\s.*$| ) {
+			# patchdata - ignore
+		} elsif ($line =~ m|^files=$|) {
+			# tshell.oby contains this line, not sure why.
+		} elsif ($line =~ m/^\s*PlatSec(Diagnostics|Enforcement|ProcessIsolation|EnforceSysBin)\s*(ON|OFF)\s*$/) {
+			# ignore platsec stuff
+		} elsif ($line =~ m/^\s*(debugport|kerneltrace|memmodel|trace|collapse|multikernel|version|bootbinary|romsize|romlinearbase|romalign|(kernel)?dataaddress|kernelheap(max|min)|defaultstackreserve|romchecksum|nowrapper|pagingpolicy)/) {
+			# rom config stuff, ignore
+		} elsif ($line =~ m/^\s*#/) {
+			# We ignore any other preprocessor directive
+		} else {
+			print "OBY line not recognised: $line\n";
+		}
+		
+		if ((defined $executableSrc) && (! ($executableSrc =~ m|eka1_entry_stub\.dll$|)) ) {
+			
+			#die "Cannot find file ${epocroot}$executableSrc\n" unless (-f "${epocroot}$executableSrc");
+			# Assume anything like BTDEBUG_DIR should equate to urel
+			$executableSrc =~ s/\\[A-Z]+_DIR\\/\\urel\\/;
+			
+			if (!(-f "${epocroot}$executableSrc")) {
+				print "WARNING: Can't find ${epocroot}$executableSrc, skipping dependancy check\n";
+				next;
+			}
+			
+			my $exeOnly = lc $executableSrc;
+			$exeOnly =~ s/.*\\//;
+			my $exeOnlyTrg = lc $executableTrg;
+			$exeOnlyTrg =~ s/.*\\//;
+			
+			my $uid3 = (headerInfo("${epocroot}$executableSrc"))[3];
+			if (defined $uid3) {
+				if ($filesByName->{$exeOnlyTrg}) {
+				  print "WARNING: 2 files with name $exeOnlyTrg in rom\n";
+			  }	
+				$filesByName->{$exeOnlyTrg} = $executableSrc;
+				if (!($uid3 eq "00000000")) {
+					$filesByUid->{$uid3} = $executableSrc;
+					print "UID3 for $executableSrc: $uid3\n" if ($verbose>1);
+				}
+			} else {
+				print "WARNING: could not find UID3 for $executableSrc\n"
+			}
+			
+			
+		}
+
+	}
+	
+	close CPP;
+	
+	
+	# now check for missing dependancies
+	my @missingFiles;
+	
+	foreach my $dependancy (keys %$filesByName) {
+	
+		my $executable = $filesByName->{$dependancy};
+
+		$cmd = "elftran -dump i ${epocroot}$executable";
+		print "running: $cmd\n" if ($verbose);
+
+		open ELFTRAN, "$cmd|" or die "Couldn't run $cmd: $!\n";
+
+		while (my $line = <ELFTRAN>) {
+			if ($line =~ m/^\d+ imports from (.*)$/) {
+				my $dep = lc($1);
+				
+				my $depName = undef;
+				my $depUid = undef;
+				
+				if ($dep =~ m/^(.*?)\{[a-f0-9]{8}\}\[([a-f0-9]{8})\]\.(.*)$/ ) {
+					unless ($ignoreDeps{lc("$1.$3")}) {
+						$depName = "$1.$3";
+						$depUid = $2;
+					}
+				} elsif ($dep =~ m/^(.*?)\{[a-f0-9]{8}\}\.(.*)$/ ) {
+					unless ($ignoreDeps{lc("$1.$2")}) {
+						$depName = "$1.$2";
+					}
+				} else {
+					print "WARNING: dependancy name '$dep' could not be parsed\n";
+				}
+				
+				
+				if (defined $depName) {
+					print "$executable links to $depName\n" if ($verbose>1);
+					if ((defined $depUid) && ($filesByUid->{$depUid})) {
+						print "Found match by UID3: $filesByUid->{$depUid} ($depUid)\n" if ($verbose>1);
+					} elsif ($filesByName->{lc($depName)}) {
+						my $uid3 = $filesByName->{lc($depName)};
+						#print "WARNING: Found match by name but not UID: $depName UID3: $uid3 expected $depUid\n";
+					} else {
+						my $fullDepName = makeFullFileName($depName);
+						if (defined $depUid) {
+							print "Missing dependancy: $depName (UID3 $depUid) required by $executable\n";
+							$filesByUid->{$depUid} = $fullDepName;
+						} else {
+							print "Missing dependancy: $depName required by $executable\n";
+						}
+						push @missingFiles, [$depName, $depUid];
+						#print "WARNING: can't find dependancy $depName at $fullDepName\n" unless (-f $fullDepName);
+						$filesByName->{lc($depName)} = $fullDepName;
+					}
+				
+				}
+			}
+		}
+
+
+
+
+		close (ELFTRAN);
+	}
+	
+	return \@missingFiles;
+	
+}
+
+
+sub ResolveMissingDeps($) {
+  my $missingFiles = shift;
+  
+	my %addedIbys;
+
+	foreach my $depInfo (@$missingFiles) {
+	
+	  my $expectedDepPath = makeFullFileName $depInfo->[0];
+	
+		# find an IBY file than contains this dependancy
+		my $ibyFile = FindIby($depInfo->[0]);
+		
+		if (defined $ibyFile) {
+			print "\nFound $depInfo->[0] in $ibyFile\n";
+		} elsif (-f $expectedDepPath) {
+			if (Query("\nCan't find IBY file for $depInfo->[0] based on components exports.\nSearch all of $romIncludeDir instead?", "yn") == 0) {
+				print "Not implemented yet, sorry!\n";
+			}
+		} else {
+	    print "IBY file for $depInfo->[0] not found, and $expectedDepPath does not exist.\n";
+	  }
+		
+		my $lineToAdd = undef;
+		if (defined $ibyFile) {
+		
+			if ($addedIbys{$ibyFile}) {
+				print "$ibyFile already included.\n";
+			} else {
+		
+				my $continue;
+				
+				do {
+					$continue = 0;			
+					my $option = Query("Do you want to include whole (I)BY file, just the one (f)ile or (n)either? (or (v)iew the IBY contents)", "ifnv");
+					if ($option==0) {
+						$addedIbys{$ibyFile}=1;
+
+						my $romIncludeMatchStr = $romIncludeDir;
+						$romIncludeMatchStr =~ s|^\w\:\\||;
+						$romIncludeMatchStr =~ s|\\|\\\\|g;
+						my $shortIby = $ibyFile;
+						$shortIby =~ s|.*$romIncludeMatchStr||i;
+						$shortIby =~ s|^\\*||;
+						$lineToAdd = "#include \"$shortIby\"";
+					} elsif ($option==1) {
+						$lineToAdd = "file=ABI_DIR\\DEBUG_DIR\\$depInfo->[0]\t\\sys\\bin\\$depInfo->[0]";
+					} elsif ($option==3) {
+						$continue=1;
+						
+						open IBYFILE, "<$ibyFile" or die "ERROR: Can't open $ibyFile: $!\n";					
+						print "$ibyFile:\n";
+						while (<IBYFILE>) {
+							print;
+						}
+						print "\n";
+					}
+				} while ($continue);
+			}
+		} elsif (-f $expectedDepPath) {
+		  if (Query("\nIBY file for $depInfo->[0] not found; include single file?", "yn")==0) {
+			  $lineToAdd = "file=ABI_DIR\\DEBUG_DIR\\$depInfo->[0]\t\\sys\\bin\\$depInfo->[0]";
+			}
+		} else {
+		  # perhaps we could search in \release\$main\$build for a binary with the required UID3 value.
+		  # might be worth implementing later?
+		  print "WARNING: $expectedDepPath does not exist, manual resolution of dependancy likely needed.\n";
+		}
+		
+		
+		
+		if (defined $lineToAdd) {
+			open OBYFILE, ">>$obyName.oby" or die "Can't append to $obyName.oby: $!\n";
+			print "Adding line:\n";
+			print "$lineToAdd\n";
+			print OBYFILE "$lineToAdd\n";
+			close OBYFILE;
+		}
+		
+	}
+	
+	print "\n";
+
+}
+
+sub FindIby($) {
+	my $file = shift;
+	my $fullFile = makeFullFileName $file;
+	return undef unless (-f $fullFile);
+	my $cmd = "bininfo $fullFile";
+	print "$cmd\n" if ($verbose);
+	
+	my @ibys;
+	my $comp = undef;
+	
+	if (open BININFO, "$cmd |") {
+		while (my $line = <BININFO>) {
+			if ($line =~ m/^Component\:\s*(.*)$/) {
+				$comp = trim($1);
+				print "$comp owns $fullFile\n" if ($verbose>1);
+			}
+		}
+		close (BININFO);
+		
+		return undef unless defined ($comp);
+
+		$cmd = "bininfo $comp";
+		print "$cmd\n" if ($verbose);
+		if (open BININFO2, "$cmd |") {
+			while (my $line = <BININFO2>) {
+				if ($line =~ m/^File\s+Status\s*$/ ) {
+					# ignore header line
+				} elsif ($line =~ m/^\s*$/ ) {
+					# ignore emptry line
+				} elsif ($line =~ m/^(.*?)\s+\w+\s*$/ ) {
+					my $file = trim($1);
+					if ($file =~ m/\.iby$/i) {
+						push @ibys, $file;
+					}
+				} else {
+					print "WARNING: could not parse bininfo output '$line'\n" if ($verbose);
+				}
+			}
+			close BININFO2;	
+		
+		} else {
+			print "WARNING: could not run '$cmd': $!\n";
+			return undef;
+		}
+		
+		
+	} else {
+		print "WARNING: could not run '$cmd': $!\n";
+		return undef;
+	}
+	
+	my $num = scalar(@ibys);
+	print "$comp owns $num IBY file(s)\n" if ($verbose);
+	
+	return undef if ($num == 0);
+	return $ibys[0] if ($num == 1);
+	
+	my $compSubName;
+	if ($comp =~ m/.*_(.*)/ ) {
+		$compSubName = $1;
+	} else {
+		$compSubName = $comp;
+	}
+	
+	my $chosenIby = undef;
+	
+	foreach my $iby (@ibys) {
+		if ($iby =~ m/\\$compSubName\.iby$/i) {
+			$chosenIby = $iby;
+			print "Choosing IBY file $iby for component $comp based on name\n" if ($verbose);
+			last;
+		}
+	}
+	
+	return $chosenIby if ((defined $chosenIby) && (CheckIbyContains($chosenIby, $file)));
+	
+	# last resort: the first iby file that contains this file
+	
+	foreach my $iby (@ibys) {
+		return $iby if (CheckIbyContains($iby, $file));
+	}
+	
+	return undef;	
+	
+}
+
+sub CheckIbyContains($$) {
+	my $iby = shift;
+	my $file = shift;
+	print "Checking for $file in $iby\n" if ($verbose>1);
+	open IBYFILE, "<$iby" or return 0;
+	
+	my $found = 0;
+	while (my $line = <IBYFILE>) {
+		if ($line =~ m/\\$file\s/i) {
+			$found = 1;
+			last;
+		}
+	}
+	
+	close IBYFILE;
+	
+	print "$iby contains $file\n" if ($found && $verbose);
+	print "$iby does not contain $file\n" if ((!$found) && $verbose);
+		
+	return $found;
+}
+
+sub headerInfo($) {
+	my $file = shift;
+	my $cmd = "elftran -dump h $file";
+	print "running: $cmd\n" if ($verbose);
+	open ELFTRANUID, "$cmd|" or die "Couldn't run $cmd: $!\n";
+	
+	my ($flags, $uid1, $uid2, $uid3) = (undef, undef, undef, undef);
+	while (my $line = <ELFTRANUID>) {
+		if ($line =~ m/^Uids:\s+([\da-f]{8})\s+([\da-f]{8})\s+([\da-f]{8})\s+\(([\da-f]{8})\)$/ ) {
+			($uid1, $uid2, $uid3) = ($1, $2, $3);
+		} elsif ($line =~ m/^Flags:\s+([\da-f]{8})$/i) {
+			$flags = $1;
+		}
+	}
+	close (ELFTRANUID);
+	return ($flags, $uid1, $uid2, $uid3);
+}
+
+
+
+sub trim($) {
+	my $str= shift;
+	$str =~ s/^\s*//g;
+	$str =~ s/\s*$//g;
+	return $str;
+}
+
+sub Query($$) {
+	my $question = shift;
+	my $options = shift;
+	local $" = '/';
+	#" fix syntax highlighting from above in CW
+	my @options = split(//, $options);
+	while (1) {
+		print "$question [@options] ";
+		my $response = lc <STDIN>;
+		chomp $response;
+
+		if (length($response)==1) {
+			if ($options =~ m/$response/g) {
+				return pos($options)-1;
+			}
+		}
+	}
+  
+}
+
+sub makeFullFileName($) {
+  my $depName = shift;
+  return "${epocroot}epoc32\\release\\$main\\$build\\$depName"
+}
+
+__END__
+
+=head1 NAME
+
+BaseRom - A tool to help you build a base ROM with selected user-side binaries.
+
+=head1 SYNOPSIS
+
+baserom [options] F<romname>
+
+options:
+
+=over
+
+=item -V variant
+
+Use the specified variant; defaults to C<h4hrp>. (note capital V).
+
+=item -t target
+
+Use the specified target architecture; defaults to C<armv5>.
+
+=item -b build
+
+Use the specified build; defaults to C<udeb>.
+
+=item -e F<\epocroot\>
+
+Use specified epocroot path instead of environment variable epocroot.
+
+=item -i F<\rom\include\directory>
+
+Use the specified directory to search for IBY files. Defaults to F<\epoc32\rom\include>.
+
+=item -o F<base.oby>
+
+Use the specified OBY file as the basis for the ROM. Defaults to F<tshell.oby>.
+
+=item -h
+
+help
+
+=item -v
+
+verbose (-vv very verbose)
+
+=item -x extraInclude
+
+If specified this file is included whenever preprocessing IBYs. It also prevents this file from being processed for dependancies itself. This option is needed when building an toolkit rom and should be set to C<-x fsh_config.iby>.
+
+=back
+
+=head1 DESCRIPTION
+
+The script is written to help you determine the dependancies that need to be included in a ROM to be able to use
+specific functionality. It also builds the appropriate OBY file.
+
+To use it:
+
+=over
+
+=item 1
+
+do a C<getsource base_e32> if you don't already have the source
+
+=item 2
+
+create a file F<myrom.oby> in F<\src\cedar\generic\base\e32\rombuild\>. In this, include the top level IBY file (or executables, etc) that 
+you need to include in your ROM. Use OBY syntax that is used by the main rombuild tool (i.e. not the base one), for example:
+
+	#include <mmf.iby>
+	file=ABI_DIR\BUILD_DIR\MyTestHarness.exe	sys\bin\MyTestHarness.exe
+
+=item 3
+
+run C<baserom myrom>. This will cause the script to create a new OBY file based on F<tshell.oby> called F<tshell_myrom.oby>.
+It will also copy any required IBY files from the default ROM include directory (F<\epoc32\rom\include> by default) into a new directory
+called F<myrom>. The format of the IBY files is converted for the base ROM building tool.
+
+=item 4
+
+The script will the check the dependancies for the executables in your ROM. Any files that are missing will be listed, and it will give
+you the option of attempting to resolve the dependancies.
+
+=item 5
+
+If you choose the resolve the dependancies, the script will search for appropriate IBY files and ask you whether you want to include
+the whole IBY file in your ROM, or just include the 1 dependancy via a C<file=> statement.
+
+=item 6
+
+Once you have worked through all the dependancies, it will start again from step 3, allowing you to iteratively resolve all your
+dependancies. Some often have to be resolved by hand, for example binaries that have a different name depending upon the variant 
+that you are building for.
+
+=item 7
+
+When you are done, it will tell you the command to use to build the ROM.
+
+=back
+
+=head1 NOTES
+
+=head2 Resolving dependancies
+
+Generally, when choosing whether or not to include an entire IBY file for a dependancy, you need to use to use some judgement. Including
+the whole IBY file has the benefit that you won't end up including a user-side DLL for a server but not the server itself. You should
+do this if you actually need to use the services provided by that server (ECOM is usually a good example of this).
+
+Including just the dependancy DLL is good if you only need to include it to satisfy linking requirements, but you never actually need to
+call into that DLL (i.e. to stop the rom build failing). For example, if your code links to F<c32.dll> but never actually uses it, it's best
+to just include that one file rather than including F<c32.iby>.
+
+Always including the whole IBY file generally results in the dependancies growing very fast until you are including pretty much the whole OS.
+
+Including F<wserv.iby> can cause problems in a C<tshell> ROM, as then you'll end up with two files trying to be F<EwSrv.exe> in the ROM.
+
+Generally, after a few iterations you can resolve most of the dependancies in your ROM, and those that remain must be done by hand, or can
+be ignored.
+
+=head3 Manually Resolving dependancies
+
+Some dependancies the script will fail to resolve automatically. For example, something that links to the screen driver F<ScDv.dll> will
+cause problems because F<ScDv.dll> doesn't exist in F<\epoc32\release\armv5\udeb> or similar places - it's actually called F<_omapqvga_scdv.dll>
+for the H4, and other things for other platforms.
+
+Generally, when the script has finished resolving dependancies automatically, you can work these out by yourself. In the example of F<ScDv.dll>, 
+looking in F<\epoc32\rom\include\base_h4hrp.iby> does the trick:
+
+	define   SCDV_DLL                _omapqvga_scdv.dll
+
+Then you can manually include the following line in your F<myrom.oby> file:
+
+	file=ABI_DIR\DEBUG_DIR\_omapqvga_scdv.dll \sys\bin\ScDv.dll
+
+The same trick for other files should work. After editing F<myrom.oby> you need to run the script on it again to update the generated OBY file.
+
+=head2 Finding IBY files
+
+When finding an IBY file for a given file, the tool does the following:
+
+=over
+
+=item 1
+
+determine the CBR component that owns the file, using C<bininfo>
+
+=item 2
+
+use C<bininfo> again to find a list of IBY files owned by that component.
+
+=item 3
+
+If it owns just 1 IBY file, use that if it includes the file we're looking for. Otherwise,
+
+=item 4
+
+Find the IBY file whose name closely matches the components name For example, for the component C<graphics_wserv> it will prefer
+an IBY file called F<wserv.iby>, or F<graphics_wserv.iby>. If one matches on this basis, use it. Otherwise,
+
+=item 5
+
+Use the first IBY file owned by the component that contains the file needed.
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright (c) 2009 - 2010 Accenture. All rights reserved.
+
+=cut
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/baserom.bat	Sat Aug 28 00:12:38 2010 +0100
@@ -0,0 +1,16 @@
+@REM baserom.bat
+@REM 
+@REM Copyright (c) 2010 Accenture. All rights reserved.
+@REM This component and the accompanying materials are made available
+@REM under the terms of the "Eclipse Public License v1.0"
+@REM which accompanies this distribution, and is available
+@REM at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@REM 
+@REM Initial Contributors:
+@REM Accenture - Initial contribution
+@REM
+@echo off
+set script=%0%
+set script=%script:.bat=%
+perl -Swx "%script%" %*
+
--- a/tools/fsh-builddocs	Thu Aug 26 15:28:08 2010 +0100
+++ b/tools/fsh-builddocs	Sat Aug 28 00:12:38 2010 +0100
@@ -1,14 +1,15 @@
 #!perl
 # fsh-builddocs
-#
+# 
 # Copyright (c) 2010 Accenture. All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the "Eclipse Public License v1.0"
 # which accompanies this distribution, and is available
 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
-#
+# 
 # Initial Contributors:
 # Accenture - Initial contribution
+#
 
 # Description:
 # fsh-builddocs - A tool that generates HTML documentation from POD source files.
--- a/tools/fsh-buildsis	Thu Aug 26 15:28:08 2010 +0100
+++ b/tools/fsh-buildsis	Sat Aug 28 00:12:38 2010 +0100
@@ -9,6 +9,7 @@
 # 
 # Initial Contributors:
 # Accenture - Initial contribution
+#
 
 # Description:
 # fsh-buildsis - A tool that generates SIS files.