Linux support for ROM building under Raptor
authorMike Kinghan <mikek@symbian.org>
Sat, 17 Jul 2010 15:09:24 +0100
changeset 26 d10c1f04b2be
parent 25 223dcf462b73
child 27 3a31ca4b29c4
Linux support for ROM building under Raptor
imgtools/romtools/group/BLD.INF
imgtools/romtools/rombuild/Armutl.pm
imgtools/romtools/rombuild/BPABIutl.pm
imgtools/romtools/rombuild/E32Plat.pm
imgtools/romtools/rombuild/E32Variant.pm
imgtools/romtools/rombuild/GCCEV5.bsf
imgtools/romtools/rombuild/romnibus.pl
--- a/imgtools/romtools/group/BLD.INF	Tue Jul 13 15:22:53 2010 +0100
+++ b/imgtools/romtools/group/BLD.INF	Sat Jul 17 15:09:24 2010 +0100
@@ -33,6 +33,12 @@
 
 ../rombuild/checkstubs.pl		/epoc32/rom/tools/checkstubs.pl
 ../rombuild/addextension.pl		/epoc32/rom/tools/addextension.pl
+../rombuild/romnibus.pl		/epoc32/rom/tools/romnibus.pl
+../rombuild/Armutl.pm		/epoc32/tools/Armutl.pm
+../rombuild/BPABIutl.pm		/epoc32/tools/BPABIutl.pm
+../rombuild/E32Plat.pm		/epoc32/tools/E32Plat.pm
+../rombuild/E32Variant.pm		/epoc32/tools/E32Variant.pm
+../rombuild/GCCEV5.bsf		/epoc32/tools/GCCEV5.bsf
 
 PRJ_MMPFILES 
 readimage 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/Armutl.pm	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,180 @@
+# Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+# this package does various ancillary things for armedg modules
+# 
+#
+
+package Armutl;
+
+require Exporter;
+@ISA=qw(Exporter);
+@EXPORT=qw(
+	Armutl_Help_Mmp
+
+	Armutl_DoMmp
+
+	Armutl_ArmIncDir
+	Armutl_ArmLibList
+	Armutl_ArmRT
+	Armutl_AsmFileList
+	Armutl_ArmVersion
+	Armutl_RVCTMajorVersion
+	Armutl_RVCTMinorVersion
+	Armutl_RVCTPatchLevel
+	Armutl_RVCTBuildNumber
+	Armutl_ArmLibDir
+);
+
+use RVCT_plat2set;
+
+my $ArmInc='';
+my @ArmLibList=();
+my $ArmRT=0;
+my @AsmFileList=();
+
+# make sure that some of the tool subroutines  still work in case of Plat() does not exists in namespace main
+my $Plat = main::Plat() if defined &main::Plat;
+
+my ($RVCTMajorVersion, $RVCTMinorVersion, $RVCTBuildNumber) = RVCT_plat2set::get_version_list($Plat);
+
+my $RVCTVersion = "$RVCTMajorVersion.$RVCTMinorVersion";
+my $RVCTPatchLevel = 0;
+
+
+sub Armutl_Help_Mmp {
+# provide the help text for START <armedg platforms> END blocks
+
+	print
+		"ARMINC  // include value of RVCT*INC environment variable to search paths\n",
+		"ARMLIBS // list the ARM supplied libraries to be linked against\n",
+		"ARMRT   // indicates this target froms part of the runtime and so\n",
+                "        // shouldn't be linked against itself or other runtime libs\n",
+	        "ARMNAKEDASM // list .cpp files subject to auto-translation from GCC inline asm to ARM embedded asm\n"
+	;
+}
+
+sub Armutl_DoMmp (@) { # takes platform text
+	my @PlatTxt=@_;
+
+	my $BaseTrg=&main::BaseTrg;
+	my $BasicTrgType=&main::BasicTrgType;
+	my $MakeFilePath=&main::MakeFilePath;
+	my $MMPFILE=&main::MmpFile;
+	my @UidList=&main::UidList;
+
+	# set up START ARMV5|THUMB2 ... END block module variables
+	my @MmpWarn=();
+	my $Line;
+
+	LINE: foreach $Line (@PlatTxt) {
+		my $LineInfo=shift @$Line;
+		$_=shift @$Line;
+		if (/^ARMINC$/o) {
+			$ArmInc = RVCT_plat2set::get_inc_path($Plat);
+			next LINE;
+		}
+		if (/^ARMRT$/o) {
+		    $ArmRT = 1;
+		    next LINE;
+		}
+		if (/^ARMLIBS$/o) {
+			my $LibVar = "RVCT${RVCTMajorVersion}${RVCTMinorVersion}LIB";
+			my $ArmLibDir = RVCT_plat2set::get_lib_path($Plat);
+
+			push @MmpWarn, "$LineInfo : No libraries specified for keyword ARMLIBS\n" unless @$Line;
+
+			while (@$Line) {
+			  my $lib = shift @$Line;
+
+              my $lib_path = RVCT_plat2set::find_lib( $Plat, $lib );
+
+              if ($lib_path)
+              {
+				  push @ArmLibList, $lib_path;
+              }
+              else
+              {
+				  push @MmpWarn, "$LineInfo : arm library file $lib not found.\n" ;
+              }
+			}
+			next LINE;
+		      }
+		if (/^ARMNAKEDASM$/o) {
+		    push @MmpWarn, "$LineInfo : No files specified for keyword ARMNAKEDASM\n" unless @$Line;
+		    push @AsmFileList, @$Line;
+		    next LINE;
+		}
+		push @MmpWarn, "$LineInfo : Unrecognised Keyword \"$_\"\n";
+	}
+
+	undef $Line;
+	if (@MmpWarn) {
+		warn
+			"\nMMPFILE \"$MMPFILE\"\n",
+			"START .. END BLOCK WARNINGS(S)\n",
+			@MmpWarn,
+			"\n"
+		;
+	}
+	undef @MmpWarn;
+    }
+
+sub Armutl_ArmIncDir() {
+    $ArmInc;
+}
+
+sub Armutl_ArmLibList() {
+    @ArmLibList;
+}
+
+sub Armutl_ArmRT() {
+    $ArmRT;
+}
+
+sub Armutl_AsmFileList() {
+    @AsmFileList;
+}
+
+sub Armutl_ArmVersion() {
+  return $RVCTVersion;
+}
+
+sub Armutl_RVCTMajorVersion() {
+  return $RVCTMajorVersion;
+}
+
+sub Armutl_RVCTMinorVersion() {
+  return $RVCTMinorVersion;
+}
+
+sub Armutl_RVCTPatchLevel() {
+  return $RVCTPatchLevel;
+}
+
+sub Armutl_RVCTBuildNumber() {
+  return $RVCTBuildNumber;
+}
+
+sub Armutl_ArmLibDir() {
+  my $LibVar = "RVCT${RVCTMajorVersion}${RVCTMinorVersion}LIB";
+  my $ArmLibDir = $ENV{$LibVar};
+  return $ArmLibDir;
+}
+
+1;
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/BPABIutl.pm	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,141 @@
+# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+# This package  does various ancillary things for BPABI (Base Platform ABI) platforms
+# 
+#
+
+package BPABIutl;
+
+require Exporter;
+@ISA=qw(Exporter);
+@EXPORT=qw(
+	BPABIutl_Plat_List
+	BPABIutl_Config_Path
+	BPABIutl_Get_Config_Variables
+);
+
+use E32Variant;
+require E32Plat;
+
+my %ConfigPath;
+my $variantABIV2Keyword = &Variant_GetMacro();
+
+sub BPABIutl_Plat_List {
+
+# Identify the BPABI platforms to be supported based on the compiler configuration files
+# present in the location specified by the environment variable "SYMBIAN_COMPILATION_CONFIG_DIR"
+# and in the directory $EPOCROOT\epoc32\tools\compilation_config
+
+	my @CompilerConfigPath;
+
+	if (exists($ENV{'SYMBIAN_COMPILATION_CONFIG_DIR'})) 
+	{
+		my $Path = $ENV{SYMBIAN_COMPILATION_CONFIG_DIR};
+		@CompilerConfigPath = split(/;/, $Path);
+	}
+
+	push @CompilerConfigPath, "$ENV{EPOCROOT}epoc32\\tools\\compilation_config";
+
+	my $ConfigDir;
+	my @BPABIPlats = ();
+
+	foreach $ConfigDir (@CompilerConfigPath)
+	{
+		opendir DIR, "$ConfigDir";
+		my @Plats=grep /\.mk$/i, readdir DIR;
+		my $Plat;
+		foreach $Plat (@Plats) 
+		{
+# The platform name will be same as the name of the configuration file <config.mk>
+# with the suffix '.mk' removed
+			$Plat =~ s/\.mk//;
+			if ($variantABIV2Keyword) {
+				if ($Plat =~ /^armv5_abiv2$/i) {
+					$Plat = "ARMV5";
+				}
+			}
+			else {
+				if ($Plat =~ /^armv5$/i) {
+					$Plat = "ARMV5_ABIV2";
+				}
+			}
+			unless (grep /$Plat$/i, @BPABIPlats) {
+				$Plat = uc $Plat;
+				push @BPABIPlats, $Plat;
+				if (!$variantABIV2Keyword && $Plat =~ /^ARMV5_ABIV2$/i) {
+					$ConfigPath{$Plat} = "$ConfigDir\\ARMV5.mk";
+				}
+				else {
+					$ConfigPath{$Plat} = "$ConfigDir\\$Plat.mk";
+				}
+			}
+		}
+	}
+	closedir DIR;
+	return @BPABIPlats;
+}
+
+sub BPABIutl_Config_Path($) {
+	my ($plat) = @_;
+# Returns the Path of the compiler configuration file
+	if (!keys(%ConfigPath))
+	{
+	    # Running for first time so initialise ConfigPath
+	    BPABIutl_Plat_List();
+	}
+	if (!$ConfigPath{$plat})
+	{
+		# Get the root platform name to support hierarchy of customizations
+		my $CustomizedPlat =  &E32Plat::Plat_Root($plat);
+
+# In default ABIV1 mode, the platform name for v2 mode of ARMV5 is ARMV5_ABIV2
+		if ( !$variantABIV2Keyword && $CustomizedPlat =~ /^ARMV5$/i ){
+			$ConfigPath{$plat} = $ConfigPath{ARMV5_ABIV2};
+		}
+
+# In default ABIV2 mode, the platform name for v2 mode of ARMV5 is ARMV5
+		elsif ( $variantABIV2Keyword && $CustomizedPlat =~ /^ARMV5$/i) {
+			$ConfigPath{$plat} = $ConfigPath{ARMV5};
+		}
+		else{
+			$ConfigPath{$plat}=$ConfigPath{$CustomizedPlat};
+		}
+	}
+	return "$ConfigPath{$plat}";
+}
+
+# routine to extract a set of variables from the compilation configuration
+# file. The variables extracted are determined by the extractvars.make file.
+# The variables are returned in a hash.
+sub BPABIutl_Get_Config_Variables
+{
+    my ($plat) = @_;
+    my $configfile = BPABIutl_Config_Path($plat);
+    my $extractvars = "$ENV{EPOCROOT}epoc32\\tools\\compilation_config\\extractvars.make";
+    my $command = "make CONFIG_FILE=$configfile -s -f $extractvars" ;
+    my $result = `$command`;
+    my %vars;
+    my @lines = split('\n', $result);
+    foreach my $line (@lines)
+    {
+	chomp $line;
+	if ($line =~ /(\w+)=(.*)/)
+	{
+	    $vars{$1} = $2;
+	}
+    }
+    return %vars;
+}
+
+1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/E32Plat.pm	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,878 @@
+# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+# Module providing platform details for platforms supported
+# by Symbian OS
+# all data is uppercase
+# 
+#
+
+package E32Plat;
+
+require Exporter;
+@ISA=qw(Exporter);
+
+@EXPORT=qw(
+	Plat_SetVerbose
+	Plat_Init
+	Plat_GetL
+	Plat_List
+	Plat_AssocIDE
+	Plat_Customizations
+	Plat_Customizes
+	Plat_Root
+	Plat_SupportsFeatureVariants
+);
+
+use BPABIutl;
+use E32Variant;
+
+my $variantABIV2Keyword = &Variant_GetMacro();
+
+my %Mode=(
+	Verbose=>0
+);
+my $ModulePath;
+
+sub Plat_SetVerbose () {
+	$Mode{Verbose}=1;
+}
+
+my %BldLists=(
+	EPOC32=>['UREL','UDEB'],
+	WINS=>['UDEB','UREL'],
+	TOOLS=>['DEB','REL'],
+	TOOLS2=>['DEB','REL'],
+);
+
+my %BldMacros=(
+	DEB=>['_DEBUG'],
+	REL=>['NDEBUG'],
+	UDEB=>['_DEBUG','_UNICODE'],
+	UREL=>['NDEBUG','_UNICODE']
+);
+
+
+my @EpocMacros=('__SYMBIAN32__');
+
+my @BPABIPlats = &BPABIutl_Plat_List;
+
+my %Plat=(
+	ARM4=>{
+		ABI=>'ARM4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+	},
+	ARM4SMP=>{
+		ABI=>'ARM4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		SMP=>1,
+		StatLink=>'ARM4SMP',
+	},
+	ARM4T=>{
+		ABI=>'ARM4T',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+	},
+	ARMI=>{
+		ASSP=>'MARM',
+		Generic=>1,
+		ASSPABI=>'',
+	},
+	SARM4=>{
+		ABI=>'ARM4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		Single=>1,
+	},
+	SARMI=>{
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		Single=>1,
+	},
+	STHUMB=>{
+		ABI=>'THUMB',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		Single=>1,
+	},
+	THUMB=>{
+		ABI=>'THUMB',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+	},
+	TOOLS=>{
+		ABI=>'TOOLS',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'TOOLS',
+		OS=>'TOOLS',
+		MakeMod=>'Cl_win',
+		MakeCmd=>'nmake',
+	},
+	TOOLS2=>{
+		ABI=>'TOOLS2',
+		ASSPABI=>'',
+		Compiler=>'GCC32',
+		CPU=>'TOOLS2',
+		OS=>'TOOLS2',
+		MakeMod=>'Cl_mingw',
+		MakeCmd=>'make',
+	},
+	CWTOOLS=>{
+		ABI=>'TOOLS',
+		ASSPABI=>'',
+		Compiler=>'CW32',
+		CPU=>'TOOLS',
+		OS=>'TOOLS',
+		MakeMod=>'Cl_tools',
+		MakeCmd=>'make',
+	},
+	VC6TOOLS=>{
+		ABI=>'TOOLS',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'TOOLS',
+		Ext=>'.DSP',
+		MakeMod=>'Ide_vc6',
+		MakeCmd=>'nmake',
+		OS=>'TOOLS',
+		Real=>'TOOLS',
+		UsrHdrsOnly=>1,
+	},
+	WINS=>{
+		ABI=>'WINS',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'WINS',
+		MakeMod=>'Cl_win',
+		MakeCmd=>'nmake',
+		OS=>'WINS',
+	},
+	VC6=>{
+		ABI=>'WINS',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'WINS',
+		Ext=>'.DSP',
+		MakeMod=>'Ide_vc6',
+		MakeCmd=>'nmake',
+		OS=>'WINS',
+		Real=>'WINS',
+		UsrHdrsOnly=>1,
+	},
+	WINSCW=>{
+		ABI=>'WINSCW',
+		ASSPABI=>'',
+		Compiler=>'CW32',
+		CPU=>'WINS',
+		MakeMod=>'Cl_codewarrior',
+		OS=>'WINS',
+		DefFile=>'WINS',	# use the MSVC def files
+	},
+	CW_IDE=>{
+		ABI=>'WINSCW',
+		ASSPABI=>'',
+		Compiler=>'CW32',
+		CPU=>'WINS',
+		Ext=>'.xml',
+		MakeMod=>'Ide_cw',
+		MakeCmd=>'make',
+		OS=>'WINS',
+		Real=>'WINSCW',
+		DefFile=>'WINS',	# use the MSVC def files
+		UsrHdrsOnly=>1,
+		SupportsMultiplePlatforms=>1,	# supports more than one real platform
+	},
+	X86=>{
+		ABI=>'X86',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'X86',
+		MakeMod=>'Cl_x86',
+		MakeCmd=>'nmake',
+		OS=>'EPOC32',
+		DefFile=>'X86',
+		Generic=>1,
+	},
+	X86SMP=>{
+		ABI=>'X86',
+		ASSPABI=>'',
+		Compiler=>'VC32',
+		CPU=>'X86',
+		MakeMod=>'Cl_x86',
+		MakeCmd=>'nmake',
+		OS=>'EPOC32',
+		DefFile=>'X86',
+		Generic=>1,
+		SMP=>1,
+		StatLink=>'X86SMP',
+	},
+	X86GCC=>{
+		ABI=>'X86gcc',
+		ASSPABI=>'',
+		Compiler=>'X86GCC',
+		CPU=>'X86',
+		MakeMod=>'Cl_x86gcc',
+		OS=>'EPOC32',
+		DefFile=>'x86gcc',
+		Generic=>1,
+	},	
+	X86GMP=>{
+		ABI=>'X86gcc',
+		ASSPABI=>'',
+		Compiler=>'X86GCC',
+		CPU=>'X86',
+		MakeMod=>'Cl_x86gcc',
+		OS=>'EPOC32',
+		DefFile=>'x86gcc',
+		Generic=>1,
+		SMP=>1,
+		StatLink=>'X86GMP',
+	},	
+	ARMV4=>{
+		ABI=>'ARMV4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'Cl_arm',
+		Compiler=>'ARMCC',
+		DefFile=>'EABI',
+		EABI=>1,
+	},
+	ARMV4SMP=>{
+		ABI=>'ARMV4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'Cl_arm',
+		Compiler=>'ARMCC',
+		DefFile=>'EABI',
+		EABI=>1,
+		SMP=>1,
+		StatLink=>'ARMV4SMP',
+	},
+	ARMV5_ABIV1=>{
+		ABI=>'ARMV5',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'Cl_arm',
+		Compiler=>'ARMCC',
+		DefFile=>'EABI',
+		EABI=>1,
+		SupportsFeatureVariants=>1,
+	},
+	ABIV2=>{
+		ABI=>'ARMV5',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'Cl_bpabi',
+		DefFile=>'EABI',
+		EABI=>1,
+		SupportsFeatureVariants=>1,
+	},
+	GCCXML=>{
+		ABI=>'ARM4',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'cl_gccxml',
+	},
+	VS6=>{
+		ABI=>'WINSCW',
+		ASSPABI=>'',
+		Compiler=>'CW32',
+		CPU=>'WINS',
+		MakeMod=>'Cl_vscw',
+		OS=>'WINS',
+		Real=>'WINSCW',
+		DefFile=>'WINS',	# use the MSVC def files
+		Ext=>'.mak'		
+	},
+	VS2003=>{
+		ABI=>'WINSCW',
+		ASSPABI=>'',
+		Compiler=>'CW32',
+		CPU=>'WINS',
+		MakeMod=>'Cl_vscw',
+		OS=>'WINS',
+		Real=>'WINSCW',
+		DefFile=>'WINS',	# use the MSVC def files
+		Ext=>'.mak'
+	},
+	EDG=>{
+		ABI=>'ARMV5',
+		ASSP=>'MARM',
+		ASSPABI=>'',
+		Generic=>1,
+		MakeMod=>'cl_edg',
+	},
+
+	# ASSP platforms should be described using .ASSP files
+	# Do not add additional ASSP platforms to this file.
+);
+
+sub Set_Plat() 
+{
+	@BPABIPlats = &BPABIutl_Plat_List;
+	foreach my $Candidate (@BPABIPlats)
+	{
+# All BPABI platforms inherit from ABIV2 properties as listed in the platlist
+# and Platlist is updated to include the BPABI platforms.
+		my ( $key, $value);
+		while (($key, $value) = each %{$Plat{ABIV2}}) {
+			$Plat{$Candidate}{$key}=$value;
+		}
+	}
+}
+
+sub Plat_SupportsFeatureVariants($)
+	{
+	my ($plat) = @_;
+
+	# In a non-ABIV2 world, ARMV5 means ARMV5_ABIV1 within e32plat content
+	if (!$variantABIV2Keyword && $plat =~ /^ARMV5$/i)
+		{
+		$plat .= "_ABIV1";
+		}
+		
+	return ($plat && defined $Plat{$plat}{SupportsFeatureVariants}) ? $Plat{$plat}{SupportsFeatureVariants} : 0;
+	}
+
+sub Plat_Customizations($) {
+        my ($plat) = @_;
+	my @empty = ();
+	return @{$Plat{$plat}{'CUSTOMIZATIONS'}} if $Plat{$plat}{'CUSTOMIZATIONS'};
+	return @empty;
+      }
+
+sub Plat_Customizes($) {
+	my ($plat) = @_;
+	return $Plat{$plat}{'CUSTOMIZES'} ? $Plat{$plat}{'CUSTOMIZES'} : "";
+}
+
+sub Plat_Root($) {
+	my ($plat) = @_;
+
+	my $RootName = $Plat{$plat}{'ROOTPLATNAME'};
+
+	if ($RootName) {
+		return $RootName;
+	}
+	else {
+		# A non-BSF platform is its own root.
+		return $plat;
+	}
+}
+
+sub Init_BSFs($) {
+	my ($Path)=@_;  
+#	get a list of modules
+	opendir DIR, $Path;
+	my @BSFs=grep s/^([^\.].*)\.BSF$/$1/, map { uc $_ } sort readdir DIR;
+	closedir DIR;
+
+	my $BSF;
+	foreach $BSF (@BSFs) {
+		my $File=$Path.$BSF.'.bsf';
+#		check whether the assp is already defined
+		if (defined %{$Plat{$BSF}}) {
+			warn(
+				"$File : warning: Platform \"$BSF\" already defined\n",
+				" ... skipping this spec\n"
+			);
+			delete $Plat{$BSF};
+			next;
+		}
+#		open the module
+		unless (open FILE, $File) {
+			delete $Plat{$BSF};
+			warn "warning: Can't open BSF specification \"$File\"\n";
+			next;
+		}
+		my $line1 = <FILE>;
+		$line1 = uc($line1);
+		unless ($line1 =~ /^\#\<BSF\>\#/) {
+			warn "warning: \"$File\" Invalid BSF specification - missing #<bsf>#\n";
+			delete $Plat{$BSF};
+			close FILE;
+                  next;
+            }
+            my $custom;
+            while ($custom = <FILE>) {
+					#skip blank lines and comments
+			delete $Plat{$BSF};
+					last unless ($custom =~ /^$|^\#/);
+            }
+            $custom = uc $custom;
+            unless ($custom =~ /^\s*CUSTOMIZES\s+(\S+)/) {
+				warn "warning: \"$File\" Invalid BSF specification - 'customizes' missing\n";
+				delete $Plat{$BSF};
+				close FILE;
+			next;
+            }
+		my $root = $1;
+		my $platname = '';
+		my $CustomizedPlatName = '';		
+
+		# In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist		
+		my $Armv5Flag = 0;
+		if (!$variantABIV2Keyword && $root =~ /^ARMV5$/i) {
+			$Armv5Flag = 1;
+		}
+
+		# Support for Hierarchy of Customizations (BSF file customization of another BSF file)
+		# 1. Check whether the BSF file customizes another BSF file.
+		# 2. If so, check whether the root BSF file has already been read.
+		# 3. If not read, then defer the current BSF file reading until the root file is read.
+		my $rootPlatFound = 0;
+		if (defined %{$Plat{$root}} || $Armv5Flag) 
+		{
+			# BSF platform customizes another valid BSF platform
+			if (defined $Plat{$root}{'CUSTOMIZES'}) 
+			{
+				$rootPlatFound = 1;
+				$platname = $root;
+				$CustomizedPlatName = $root;
+
+				# Set the root platform name which is same as of customizes platform
+				$Plat{$BSF}{'ROOTPLATNAME'} = $Plat{$root}{'ROOTPLATNAME'};
+			}
+			# BSF platform customizes to one of the existing ABI platforms
+			else
+			{
+				# All BPABI platforms inherits from ABIV2 platform listed in the platlist
+				if (grep /^$root$/i, @BPABIPlats) {
+					$platname = "ABIV2";
+				}
+				elsif ($Armv5Flag) {
+				# In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist
+					$platname = "ARMV5_ABIV1";	
+				}
+				else {
+					$platname = $root;
+				}
+				
+				$CustomizedPlatName=$root;
+
+				# BSF File check Begins 
+				# The following check is included to handle the existing BSF files which has to behave in different manner
+				# in default v1 mode and v2 mode. The following code changes the BSF name and the custmoized platform name
+				# to the implied names. This is done to support switching between v1 and v2 modes by enabling the keyword in
+				# the variant configuration file.
+				# In v1 mode, the ARMV6_ABIV1 => ARMV6 platform and ARMV6 => ARMV6_ABIV2 platform.
+				if (!$variantABIV2Keyword) {
+					if ($BSF =~ /^ARMV6_ABIV1$/i) {
+						$BSF = "ARMV6";	
+						$CustomizedPlatName = "ARMV5";	
+					}
+					elsif ($BSF =~ /^ARMV6$/i) {
+						$BSF = "ARMV6_ABIV2";	
+						$CustomizedPlatName = "ARMV5_ABIV2";
+						$platname = "ABIV2";
+					}
+				}
+				# BSF File check Ends
+
+				# Set the root platform name
+				$Plat{$BSF}{'ROOTPLATNAME'} = $CustomizedPlatName;
+			}			
+		}
+		else
+		{
+			my $rootbsf = $Path.$root.".bsf";			
+			if ( -e $rootbsf ) {
+				# BSF file customizes another BSF file which has not been read yet.
+				# So defer current BSF file reading until the root BSF file is read.				
+				delete $Plat{$BSF};
+				push(@BSFs, $BSF);
+				next;		
+			}
+		}
+		# If the customizes platform is not a valid BSF platform or BPABI platorm or ARMV5 or ARMV5_ABIV1,
+		# then throw warning.
+		unless ($rootPlatFound || $root =~ /^ARMV5(_ABIV1)?$/ || (grep /^$root$/i, @BPABIPlats)) {
+			warn "warning: \"$File\" Invalid BSF specification - customization restricted to ARMV5, ABIv2 and valid BSF platforms\n";
+			close FILE;
+			delete $Plat{$BSF};
+			next;
+		}
+			
+		my ( $key, $value);
+		while (($key, $value) = each %{$Plat{$platname}}) {
+			$Plat{$BSF}{$key}=$value;
+		}
+		
+		push @{$Plat{$CustomizedPlatName}{'CUSTOMIZATIONS'}}, $BSF;
+		$Plat{$BSF}{'CUSTOMIZES'} = $CustomizedPlatName;
+		while (<FILE>) {
+			next if (/^$|^\#/);
+			if (/^\s*SMP\s*$/i) {
+				$Plat{$BSF}{'SMP'} = 1;
+				$Plat{$BSF}{'StatLink'} = lc $BSF;
+				next;
+			}
+			$Plat{$BSF}{'CUSTOMIZATION_DATA'} .= $_;
+		}
+		# BSF file statements will have newline character("\n") at the end, except for the last statement.
+		# So append "\n" for the last BSF file statement.
+		# "\n" will be used to split BSF statements to support hierarchy of customizations.
+		$Plat{$BSF}{'CUSTOMIZATION_DATA'} .= "\n";
+		close FILE;
+	}
+	1;
+}
+
+sub Plat_Init ($) { # takes path to ASSP modules
+	my ($Path)=@_;
+
+	my %PlatHashKeys=(
+		ABI=>1,
+		ASSPABI=>1,
+		SINGLE=>1,
+		Compiler=>1,
+		CPU=>1,
+		MakeMod=>1,
+		MakeCmd=>1,
+		OS=>1,
+		DefFile=>1,
+		ASSP=>1,
+	);
+
+#	Include the list of BPABI platforms
+	&Set_Plat;
+
+	Init_BSFs($Path);
+
+#	get a list of modules
+	opendir DIR, $Path;
+	my @_ASSPs=grep s/^([^\.].*)\.ASSP$/$1/, map { uc $_ } readdir DIR;
+	closedir DIR;
+
+	my @ASSPs;
+	foreach (@_ASSPs) {
+		if (!$ENV{USEARMCC} and /EDG$/i) {
+#			warn(
+#				"Note: ASSP \"$_\" disabled\n"
+#			);
+
+			next;
+		}
+		push @ASSPs, $_;
+	}
+
+#	open each module in turn, and add it to the array
+	my $ASSP;
+	foreach $ASSP (@ASSPs) {
+		my $File=$Path.$ASSP.'.assp';
+#		check whether the assp is already defined
+		if (defined %{$Plat{$ASSP}}) {
+			warn(
+				"$File : warning: ASSP \"$ASSP\" already defined\n",
+				" ... skipping this module\n"
+			);
+
+			next;
+		}
+#		open the module
+		unless (open FILE, $File) {
+			warn "warning: Can't open assp module \"$File\"\n";
+			next;
+		}
+		my %Data=();
+		my %SingleData=();
+		my $MatchingSingle="";
+		my @Errors=();
+		while (<FILE>) {
+#			strip comments
+			s/^([^#]*)#.*$/$1/o;
+#			skip blank lines
+			if (/^\s*$/o) {
+				next;
+			}
+#			get the key-value pair
+			unless (/^\s*(\w+)\s+(\w+)\s*$/o) {
+				push @Errors, "$File($.) : warning: syntax error - only key-value pairs allowed\n";
+				next;
+			}
+			my ($Key, $Val)=($1, $2);
+			if ($PlatHashKeys{$Key}!=1) {
+				push @Errors, "$File($.) : warning: unrecognized keyword - $Key\n";
+				next;
+			}
+			if ($Key eq "SINGLE") {
+				$SingleData{Single} = 1;
+				$SingleData{ASSP} = $ASSP;
+				$MatchingSingle = uc $2;
+			} else {
+				$Data{$Key}=$Val;
+				$SingleData{$Key}=$Val;
+			}
+		}
+		close FILE;
+		if (@Errors) {
+			warn(
+				@Errors,
+				" ... skipping this module\n"
+			);
+			next;
+		}
+# change -  Allow ASSPs to pick up all the options of the ABI they specify, 
+# in particular the compiler they need.
+			$Data{'ASSP'} = $ASSP unless $Data{'ASSP'};
+			if ($Plat{$Data{'ABI'}}) {
+			foreach (keys %{$Plat{$Data{'ABI'}}}) {
+			$Data{$_} = $Plat{$Data{'ABI'}}{$_} unless ($_ =~ /^GENERIC$/i) or $Data{$_};
+			}
+		}
+
+		%{$Plat{$ASSP}}=%Data;
+		if ($MatchingSingle ne "") {
+			foreach (keys %Data) {
+			$SingleData{$_} = $Data{$_} unless ($_ =~ /^GENERIC$/i) or $SingleData{$_};
+			}
+			%{$Plat{$MatchingSingle}}=%SingleData;
+		}			
+	}
+}
+
+sub Plat_GetL ($$$$) { # takes Platform name, ref to plat hash, ref to bldmacrohash, bldmake plat command notifier
+	my ($Candidate,$PlatHash_ref,$BldMacrosHash_ref,$platcommand)=@_;
+	$Candidate=uc $Candidate;
+
+# is platform in our list?
+	unless (defined $Plat{$Candidate}) {
+
+		# is platform BPABI compliant one?
+		if (!$variantABIV2Keyword && $Candidate eq 'ARMV5') {
+		}
+		elsif (not(grep /^$Candidate$/i, @BPABIPlats))
+		{
+			die "ERROR: Platform \"$Candidate\" not supported\n";
+		}
+	}
+
+	my $BPABIPlat;
+	my %PlatHash=();
+
+# check the data
+# All BPABI platforms inherit ABIV2 properties 
+	if (grep /^$Candidate$/i, @BPABIPlats) 
+	{
+		$BPABIPlat='ABIV2';
+		%PlatHash=%{$Plat{$BPABIPlat}};
+	}
+# In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist
+	elsif (!$variantABIV2Keyword && $Candidate eq 'ARMV5') {
+		%PlatHash=%{$Plat{ARMV5_ABIV1}};
+	}
+	else {
+		%PlatHash=%{$Plat{$Candidate}};
+	}
+
+# set the defaults
+	$PlatHash{Name}=$Candidate;
+	$PlatHash{Real}=$PlatHash{Name} unless $PlatHash{Real};
+	$PlatHash{Ext}=".$PlatHash{Real}" unless $PlatHash{Ext};
+	$PlatHash{ASSP}=$PlatHash{Real} unless $PlatHash{ASSP};
+
+# Get the root platform name to support hierarchy of customizations
+	my $CustomizedPlat=$PlatHash{'ROOTPLATNAME'};
+
+	if ((defined($Candidate)  && ($Candidate =~ /^ARMV5/i)) || (defined($CustomizedPlat) && ($CustomizedPlat =~ /^ARMV5/i))) {
+# Compiler name should be set as ARMCC for all ARMV5 platforms
+		$PlatHash{Compiler}='ARMCC';
+		$PlatHash{Toolchain}='rvct22';
+	}
+	elsif ($BPABIPlat) {
+# Compiler name should be set as that of platform name for all BPABI platforms
+		$PlatHash{Compiler}=$Candidate;
+		$PlatHash{Toolchain}=$Candidate;
+	}
+	elsif ($CustomizedPlat) {
+# Compiler name should be set as that of the customized platform name incase of customization
+		$PlatHash{Compiler}=$CustomizedPlat;
+		$PlatHash{Toolchain}=$CustomizedPlat;
+	}
+
+	$PlatHash{Compiler}='GCC32' unless $PlatHash{Compiler};
+	$PlatHash{OS}='EPOC32' unless $PlatHash{OS};
+	$PlatHash{MakeMod}='Cl_gcc' unless $PlatHash{MakeMod};
+	$PlatHash{MakeCmd}='make' unless $PlatHash{MakeCmd};
+	$PlatHash{CPU}='MARM' unless $PlatHash{CPU};
+	$PlatHash{Single}=0 unless $PlatHash{Single};
+	$PlatHash{UsrHdrsOnly}=0 unless $PlatHash{UsrHdrsOnly};
+	$PlatHash{Generic}=0 unless $PlatHash{Generic}; # generic means "for a target device but no particular ASSP"
+	$PlatHash{SupportsMultiplePlatforms}=0 unless $PlatHash{SupportsMultiplePlatforms};
+
+	$PlatHash{ABI}='ARMI' unless $PlatHash{ABI};
+	$PlatHash{ASSPABI}='ARM4' unless defined $PlatHash{ASSPABI};
+
+	unless (defined $PlatHash{DefFile}) {
+		if ($PlatHash{Compiler} eq 'VC32') {
+			$PlatHash{DefFile}='WINS';
+		} else {
+			$PlatHash{DefFile}='MARM';
+		}
+	}
+	
+# .MMP macros - keeping the order is useful
+	@{$PlatHash{MmpMacros}}=$PlatHash{Compiler};
+	push @{$PlatHash{MmpMacros}}, $PlatHash{OS};
+	push @{$PlatHash{MmpMacros}}, $PlatHash{CPU} unless $PlatHash{CPU} eq $PlatHash{OS};
+	push @{$PlatHash{MmpMacros}}, $PlatHash{ASSP} unless $PlatHash{ASSP}=~/^($PlatHash{CPU}|$PlatHash{OS})$/;
+
+	if ($PlatHash{Single}) {
+		push @{$PlatHash{MmpMacros}}, 'SINGLE';
+	}
+	if ($PlatHash{SMP}) {
+		push @{$PlatHash{MmpMacros}}, 'SMP';
+	}
+	if ($PlatHash{EABI}) {
+		push @{$PlatHash{MmpMacros}}, 'EABI';
+	}
+	if ($PlatHash{Compiler} eq 'VC32') {
+		my $MSVCVer = &Winutl_MSVCVer($platcommand);
+		my $MSVCSubVer = &Winutl_MSVCSubVer($platcommand);
+		push @{$PlatHash{MmpMacros}}, 'MSVC'.$MSVCVer;
+		push @{$PlatHash{MmpMacros}}, 'MSVC'.$MSVCVer.$MSVCSubVer;
+		if ($MSVCVer > 6) {
+			push @{$PlatHash{MmpMacros}}, 'MSVCDOTNET';
+		}
+	}
+	if ($PlatHash{Compiler} eq 'ARMCC') {
+		my ($MajVer, $MinVer) = RVCT_plat2set::get_version_list($Candidate);
+		push @{$PlatHash{MmpMacros}}, 'ARMCC_'.$MajVer;
+		push @{$PlatHash{MmpMacros}}, 'ARMCC_'.$MajVer.'_'.$MinVer;
+	}
+	
+	if ($PlatHash{Compiler} eq 'X86GCC') {	
+			push @{$PlatHash{MmpMacros}}, 'GCC32';
+	}
+
+	## TOOLS2 Specific Macros ##
+	
+	if ($PlatHash{Compiler} eq 'GCC32') {
+		push @{$PlatHash{MmpMacros}}, 'MINGW32';
+		push @{$PlatHash{MmpMacros}}, '_STLP_LITTLE_ENDIAN';
+		
+	}
+
+    # add GCCXML to the mmp macro list, so we can filter out stuff in bld.inf files and mmps.
+    # note that this mean that __GCCXML__ is automacally routed to makefile, so we can take out explicit call. 
+    if( $PlatHash{Name} eq "GCCXML") {
+        push @{$PlatHash{MmpMacros}}, 'GCCXML';
+    }
+	
+# add specific platform macros for platforms customising others.
+	if (Plat_Customizes($PlatHash{Name})) {
+		push @{$PlatHash{MmpMacros}}, $PlatHash{Name} unless grep /$PlatHash{Name}/, @{$PlatHash{MmpMacros}};
+	}
+
+# compilation macros
+	@{$PlatHash{Macros}}=@EpocMacros;
+	foreach (@{$PlatHash{MmpMacros}}) {
+		## If STLP_LTTLE_ENDIAN is used, then dont append __ to the macro name ##
+		if ($_ =~ m/STLP_LITTLE_ENDIAN/) {
+			push @{$PlatHash{Macros}}, $_;
+		} else {
+		push @{$PlatHash{Macros}}, '__'.$_.'__';
+		}
+	}
+
+#	extra special .MMP macros which aren't applied for compilation
+	if ($PlatHash{Generic}) {
+		push @{$PlatHash{MmpMacros}}, "GENERIC_$PlatHash{CPU}";
+		if ($PlatHash{CPU} eq 'MARM') {
+#			we can't define this for ASSP platforms because we won't be sure what
+#			the ABI is until we've processed the .MMP file
+			push @{$PlatHash{MmpMacros}}, "MARM_$PlatHash{ABI}";
+		}
+	}
+
+# builds
+	@{$PlatHash{Blds}}=@{$BldLists{$PlatHash{OS}}};
+
+# output some information
+	if ($Mode{Verbose}) {
+		print
+			"Platform         $PlatHash{Name}\n",
+			"Real Name        $PlatHash{Real}\n",
+			"Compiler         $PlatHash{Compiler}\n",
+			"OS               $PlatHash{OS}\n",
+			"CPU              $PlatHash{CPU}\n",
+			"ASSP             $PlatHash{ASSP}\n",
+			"ABI              $PlatHash{ABI}\n",
+			"ASSPABI          $PlatHash{ASSPABI}\n",
+			"Makefile Module  $PlatHash{MakeMod}\n",
+			"Makefile Type    $PlatHash{MakeCmd}\n",
+			"MMP Macros       @{$PlatHash{MmpMacros}}\n",
+			"Macros           @{$PlatHash{Macros}}\n",
+			"Blds             @{$PlatHash{Blds}}\n"
+		;
+	}
+
+	%{$PlatHash_ref}=%PlatHash;
+	%{$BldMacrosHash_ref}=%BldMacros;
+}
+
+sub Plat_List () {
+
+#	Include the list of BPABI platforms
+	&Set_Plat;
+
+#	return list of supported platforms
+
+	#sort keys %Plat;
+	my @PlatList;
+	my $Key;
+	foreach $Key (keys %Plat) {
+		if (!$variantABIV2Keyword && $Key =~ /^armv5_abiv1$/i) {
+			$Key = 'ARMV5';
+		}
+		unless (grep /^$Key$/i, @PlatList) {
+			push @PlatList, $Key;
+		}
+	}
+	return @PlatList
+}
+
+sub Plat_AssocIDE ($$) {
+#	return the IDE associated with a "Real" platform if there is one
+	my ($Candidate, $AssocIDEs)=@_;
+
+	unless (defined $Plat{$Candidate}) {
+		die "ERROR: Platform \"$Candidate\" not supported\n";
+	}
+
+	my $Key;
+	foreach $Key (keys %Plat) {
+		if (${Plat{$Key}}{Real}) {
+			if (${Plat{$Key}}{Real} eq $Candidate) {
+				push @$AssocIDEs, $Key;
+			}
+		}
+	}
+}
+
+1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/E32Variant.pm	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,156 @@
+# Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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 E32Variant;
+
+require Exporter;
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(Variant_GetMacroList Variant_GetMacroHRHFile Variant_GetMacro);
+
+use Pathutl;
+
+# using $FindBin::Bin to figure out the location of the epoc32\tools directory as 
+# IDE doesn't understand env{EPOCROOT}
+
+my $PerlBinPath;	# fully qualified pathname of the directory containing this script
+
+BEGIN {
+	require 5.005_03;		# check user has a version of perl that will cope
+	$PerlBinPath = $FindBin::Bin;	# X:/epoc32/tools
+	$PerlBinPath =~ s/\//\\/g;	# X:\epoc32\tools
+}
+
+# get epocroot if it is set
+my $epocroot = $ENV{EPOCROOT};
+my $toolspath;
+
+#if epocroot is not set figure it out
+if(!$epocroot){
+    $epocroot = $PerlBinPath . "\\..\\..\\" ; #infer epocroot
+    $toolspath = $PerlBinPath;
+}else{
+    $toolspath = $epocroot . "epoc32\\tools\\";
+}
+
+$epocroot=~s/^(.:)//io;    # remove drive letter
+$epocroot=&Path_Strip($epocroot); # collapse
+
+my $cfgFile =  $toolspath . "variant\\variant.cfg"; # default location
+$cfgFile =~ /^(.:)/i; # match the drive
+my $MacroHRHLocation_Drive = lc($1); # save the drive 
+
+sub Variant_GetMacroHRHFile{
+    my $file;
+    if(-e $cfgFile){
+	open(FILE, $cfgFile) || die "\nCould not open: " . $cfgFile ."\n";
+	while (<FILE>) {
+	    # strip comments
+	    s/^([^#]*)#.*$/$1/o;
+	    # skip blank lines
+	    if (/^\s*$/o) {
+		next;
+	    }
+	    # get the hrh file
+	    if($_ =~ /\.hrh/xi){
+		$file = $_; 
+		last;
+	    }
+	}
+	close FILE;
+	die "\nERROR: No variant file specified in $cfgFile!\n" unless $file;
+	$file =~ s/\s+//g;
+	$file=~s/^(.:)//io;    # remove drive letter
+	my $paths_drive = lc($1);
+
+	$file = Path_MakeEAbs($epocroot."EPOC32\\", $epocroot, $file); # assume relative to EPOCROOT
+
+	if($paths_drive){
+	    die "\nERROR: Variant file specified in $cfgFile is not on the same drive as \\epoc32\\\n" 
+		unless ($paths_drive eq $MacroHRHLocation_Drive);
+	}
+	if(!(-e $file)) {
+	    die "\nERROR: $cfgFile specifies $file which doesn't exist!\n";
+	}
+
+	# make sure it is in dos syntax
+	$file=~ s/\//\\/g;
+    }
+    return $file;
+}
+
+
+# returns the variant specific macro definitions as a list
+sub Variant_GetMacroList{
+
+    my @macros = ();
+    my $vfile = Variant_GetMacroHRHFile();
+    
+    if($vfile)
+    {
+	my $VariantFilePath = Path_Split('Path',$vfile);
+	chop( $VariantFilePath );
+	$VariantFilePath = &Path_PrefixWithDriveAndQuote($VariantFilePath);
+	$vfile = &Path_PrefixWithDriveAndQuote($vfile);
+	my $e32Path = &Path_PrefixWithDriveAndQuote($epocroot."epoc32\\include");
+	
+	open CPPPIPE,"cpp -I $e32Path -I $VariantFilePath -undef -dM $vfile |" or die "ERROR: Can't invoke CPP.EXE\n";
+	while(<CPPPIPE>){
+	    if($_ =~ /(\#define)(\s+)(.+)/){
+		push @macros, $3;
+	    }
+	}
+	close CPPPIPE;
+    }
+    return @macros;
+}
+
+sub Variant_GetMacro{
+
+    my $file;
+    if(-e $cfgFile){
+	open(FILE, $cfgFile) || die "\nCould not open: " . $cfgFile ."\n";
+	while (<FILE>) {
+	    # strip comments
+	    s/^([^#]*)#.*$/$1/o;
+	    # skip blank lines
+	    if (/^\s*$/o) {
+		next;
+	    }
+	    # get the hrh file
+	    if($_ =~ /^ENABLE_ABIV2_MODE$/xi){
+		close FILE;
+		return 1;
+	    }
+	}
+	close FILE;
+    }
+    return 0;
+}
+
+1;
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/GCCEV5.bsf	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,20 @@
+#<bsf>#
+# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+# This BSF file is to support building for the ARMV6 architecture.
+
+CUSTOMIZES GCCE
+
+INVARIANT_OPTIONS -march=armv5 -mapcs -mthumb-interwork
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/romnibus.pl	Sat Jul 17 15:09:24 2010 +0100
@@ -0,0 +1,1052 @@
+#!/usr/bin/perl
+#
+# 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:
+# Mike Kinghan, mikek@symbian.org, for Symbian Foundation
+#
+# Description:
+#
+
+# romnibus.pl - Build a rom like rom_sbs.pl but without Windows dependencies.
+#
+# Pre-processes the .oby/iby files then invokes rombuild.exe
+# (or other specified builder)
+
+# First, read our config file
+
+use strict;
+use Getopt::Long;
+use Cwd;
+use Cwd 'abs_path';
+use File::Spec;
+
+my $on_windows;
+my $epocroot_vol;
+my $epocroot_dir;
+my $epocroot_file;
+my %dir_listings = ();	
+my %opts=();
+my $param_count = scalar(@ARGV);
+my (@assps, @builds, %variants, @templates, %flags, %insts, %zip, %builder);
+my $main;
+my $kmain;
+my $toroot;
+my $e32path;
+my $rombuildpath;
+my $euserdir;
+my $elocldir;
+my $kbdir;
+my $romname;
+my $single;
+my $smain;
+my $pagedCode;
+my $debug;
+my $quiet;
+my $drive;
+my $toolpath;
+my $epoc32path;
+my $epocroot;
+my $drive = "";
+my $base_path;
+my $line;
+sub Variant_GetMacroHRHFile;
+sub is_RVCT_build($);
+sub parse_cfg;
+sub ASSPS;
+sub BUILDS;
+sub TEMPLATES;
+sub usage;
+sub rectify($$$);
+sub match_abbrev($$);
+sub check_opts;
+sub lookup_file_info($$);
+sub lookupSymbolInfo($$);
+sub parse_patch_data($$);
+sub gen_file;
+sub nix_fixes {
+#	Fix case-sensitivity offenders for unix/linux environment.
+	my $e32plat_pm = File::Spec->catfile($toolpath,"e32plat.pm");
+	my $armutl_pm = File::Spec->catfile($toolpath,"armutl.pm");
+	my $bpabiutl_pm = File::Spec->catfile($toolpath,"bpabiutl.pm");
+	my $e32variant_pm = File::Spec->catfile($toolpath,"e32variant.pm");
+	my $E32Plat_pm = File::Spec->catfile($toolpath,"E32Plat.pm");
+	my $Armutl_pm = File::Spec->catfile($toolpath,"Armutl.pm");
+	my $BPABIutl_pm = File::Spec->catfile($toolpath,"BPABIutl.pm");
+	my $E32Variant_pm = File::Spec->catfile($toolpath,"E32Variant.pm");
+	# Create symlinks for case-sensitively misnamed modules we need.
+	unless ( -f $E32Plat_pm or -l $E32Plat_pm) {
+		symlink($e32plat_pm,$E32Plat_pm);
+	}
+	unless ( -f $Armutl_pm or -l $Armutl_pm) {
+		symlink($armutl_pm,$Armutl_pm);
+	}
+	unless ( -f $BPABIutl_pm or -l $BPABIutl_pm) {
+		symlink($bpabiutl_pm,$BPABIutl_pm);
+	}
+	unless ( -f $E32Variant_pm or -l $E32Variant_pm) {
+		symlink($e32variant_pm,$E32Variant_pm);
+	}
+	# Make uppercase symlinks to all .bsf files in /epoc32/tools
+	my @bsf_files = glob(File::Spec->catfile($toolpath,"*.bsf"));
+	foreach my $bsf_file (@bsf_files) {
+		my ($vol,$dirs,$file) = File::Spec->splitpath($bsf_file);
+		$file =~ /^(\S+)\.bsf/;
+		my $uc_stem = uc($1);
+		my $uc_bsf_file = File::Spec->catpath($vol,$dirs,($uc_stem .".bsf"));
+		unless ( -f $uc_bsf_file or -l $uc_bsf_file ) {
+			symlink($bsf_file,$uc_bsf_file) or die "Can't symlink $bsf_file -> $uc_bsf_file. $!";
+		}
+	}
+}
+
+
+BEGIN {
+	$on_windows = $^O =~ /^MSWin/ ? 1 : 0;
+	$epocroot = $ENV{EPOCROOT};
+	die "ERROR: Must set the EPOCROOT environment variable.\n" if (!defined($epocroot));
+	print "Environmental epocroot - >$epocroot<\n";
+	$epocroot = abs_path($epocroot);
+	die "ERROR: EPOCROOT must specify an existing directory.\n" if (!-d $epocroot);
+	($epocroot_vol,$epocroot_dir,$epocroot_file) = File::Spec->splitpath($epocroot);
+	$epocroot = File::Spec->catfile(($epocroot_vol,$epocroot_dir,$epocroot_file),undef);
+	print "EPOCROOT=$ENV{EPOCROOT} resolved as \"$epocroot\"\n";
+	$epoc32path = "${epocroot}epoc32";
+	$toolpath = File::Spec->catfile($epoc32path,"tools");
+	push @INC, $toolpath;
+	nix_fixes(), unless ($on_windows);
+}
+
+
+my $result = GetOptions (\%opts, "assp=s",
+						 "inst=s",
+						 "type=s",
+						 "variant=s",
+						 "build=s", 
+						 "conf=s",
+						 "name=s",
+						 "modules=s",
+						 "xabi=s",
+						 "clean",
+						 "quiet",
+						 "help",
+						 "debug",
+						 "zip",
+						 "symbol",
+						 "noheader",
+						 "kerneltrace=s",
+						 "rombuilder=s",
+						 "define=s@",
+						 "rofsbuilder=s",
+						 "compress",
+						 );
+
+$debug = $opts{debug};
+$quiet = $opts{quiet} unless $debug;
+
+if ($on_windows) {
+	#The cpp needed a drive apparently
+	$drive = $epocroot_vol;
+	$epoc32path = File::Spec->catpath($epocroot_vol,$epoc32path,undef);
+}
+
+my $cwd = Cwd::cwd();
+my ($vol,$dirs,$file) = File::Spec->splitpath($cwd);
+my @path_parts = File::Spec->splitdir($dirs);
+while(@path_parts[-1] ne "sf") {
+	pop(@path_parts);
+}
+$e32path = File::Spec->catdir((@path_parts,"os"));
+$base_path = $e32path; # ??
+$rombuildpath = File::Spec->catfile($e32path,"kernelhwsrv","kernel","eka","rombuild");
+
+use E32Plat;
+{
+        Plat_Init($toolpath . ($on_windows ? '\\' : '/'));
+}
+
+if ($debug) {
+	print "epocroot = $epocroot\n";
+	print "epoc32path = $epoc32path\n";
+	print "drive = $drive\n";
+	print "toolpath = $toolpath\n";
+	print "toroot = $toroot\n";
+	print "e32path = $e32path\n";
+	print "rombuildpath = $rombuildpath\n";
+	print "base_path = $base_path\n";
+}
+
+my $cppflags="-P -undef -Wno-endif-labels -traditional -lang-c++ -nostdinc -iwithprefixbefore $rombuildpath -I $rombuildpath -I $drive$epoc32path ";
+
+# Include variant hrh file defines when processing oby and ibys with cpp
+# (Code copied from \\EPOC\master\cedar\generic\tools\romkit\tools\buildrom.pm -
+# it used relative path to the working dir but we are using absolute path seems neater)
+
+my $variantMacroHRHFile = Variant_GetMacroHRHFile();
+if($variantMacroHRHFile){
+	my ($ignore1,$dir,$file) = File::Spec->splitpath($variantMacroHRHFile);
+	$cppflags .= " -I " . File::Spec->catpath($epocroot_vol,$dir,undef) . " -include " . File::Spec->catpath($epocroot_vol,$dir,$file); 
+}
+
+if($param_count == 0 || $opts{'help'} || !$result) {
+	usage();
+	exit 0;
+}
+
+# Now check that the options we have make sense
+
+checkopts();
+
+if (!$quiet) {
+	print "Starting directory: ", Cwd::cwd(), "\n";
+	print <<EOF;
+OPTIONS:
+\tTYPE: $opts{'type'}
+\tVARIANT: $opts{'variant'}
+\tINSTRUCTION SET: $opts{'inst'}
+\tBUILD: $opts{'build'}
+\tMODULES: $opts{'modules'}
+EOF
+}
+
+#Pick out the type file
+my $skel = "$opts{'type'}.oby";
+unless (-e $skel) {
+	$skel= File::Spec->catfile($rombuildpath,"$opts{'type'}.oby");
+}
+unless (-e $skel) {
+	die "Can't find type file for type $opts{'type'}, $!";
+}
+
+print "Using type file $skel\n" if !$quiet;
+
+# If clean is specified, zap all the image and .oby files
+
+if($opts{'clean'}) {
+	unlink glob("*.img");
+	unlink "rom.oby";
+	unlink "rombuild.log";
+	unlink glob("*.rofs");
+	unlink "rofsbuild.log";
+}
+
+# Now pre-pre-process this file to point to the right places for .ibys
+# Unfortunately cpp won't do macro replacement in #include strings, so
+# we have to do it by hand
+
+my $k = $opts{kerneltrace};
+
+if ($opts{assp}=~/^m(\S+)/i) {
+	$kbdir="kb$1";
+	$kbdir="kbarm" if (lc $1 eq 'eig');
+} else {
+	$kbdir="kb$opts{assp}";
+}
+$single=1 if ($opts{assp}=~/^s(\S+)/i);
+
+if ($single) {
+	# Hackery to cope with old compiler
+	if ($main eq 'MARM') {
+		$smain='SARM';
+	} else {
+		$smain="S$main";
+	}
+} else {
+	$smain=$main;
+}
+
+open(X, "$skel") || die "Can't open type file $skel, $!";
+open(OUT, "> rom1.tmp") || die "Can't open output file, $!";
+
+# First output the ROM name
+print OUT "\nromname=$romname\n";
+while(<X>) {
+	unless ($on_windows) {
+		if (m/#include/) {
+			s|\\|\/|g;
+		}
+	}
+	s/\#\#ASSP\#\#/$opts{'assp'}/;
+	s/\#\#VARIANT\#\#/$opts{'variant'}/;
+	s/\#\#BUILD\#\#/$opts{'build'}/;
+	s/\#\#MAIN\#\#/$main/;
+	s/\#\#KMAIN\#\#/$kmain/;
+	s/\#\#E32PATH\#\#/$e32path/;
+	s/\#\#BASEPATH\#\#/$base_path/;
+	s/\#\#EUSERDIR\#\#/$euserdir/;
+	s/\#\#ELOCLDIR\#\#/$elocldir/;
+	s/\#\#KBDIR\#\#/$kbdir/;
+	print OUT;
+}
+
+close X;
+close OUT;
+
+# Use cpp to pull in include chains and replace defines
+
+my $defines = "";
+$defines .= "-D MAIN=$main ";
+$defines .= "-D KMAIN=$kmain ";
+$defines .= "-D EUSERDIR=$euserdir ";
+$defines .= "-D ELOCLDIR=$elocldir ";
+$defines .= "-D E32PATH=$e32path ";
+$defines .= "-D BASEPATH=$base_path ";
+$defines .= "-D EPOCROOT=$epocroot ";
+$defines .= "-D SMAIN=$smain " if $smain;
+
+foreach (@{$opts{'define'}}) {
+	my @array=split(/,/,$_);
+	foreach (@array) {
+		$defines.="-D ".uc $_." ";
+		$pagedCode = 1 if $_ eq 'PAGED_CODE';
+		}
+	}
+
+if ($opts{'modules'}) {
+	my @array=split(/,/,$opts{'modules'});
+	foreach (@array) {
+		$defines.="-D ".uc $_." ";
+		}
+	}
+
+foreach (keys %opts) {
+	next if ($_ eq 'name');
+	next if ($_ eq 'modules');
+	next if ($_ eq 'zip');
+	next if ($_ eq 'symbol');
+	next if ($_ eq 'kerneltrace');
+	next if ($_ eq 'define');
+	$defines.="-D ".uc $_."=".$opts{$_}." ";
+	$defines.="-D ".uc $_."_".$opts{$_}." ";
+}
+
+$defines.="-D SINGLE " if ($single);
+$defines.="-D RVCT " if (IsRVCTBuild($main));
+
+print "Using defines $defines\n" if !$quiet;
+
+my $ret=1;
+my $cppcmd;
+if($opts{'build'}=~/^u/i and $on_windows) {
+	# Unicode build
+	$cppcmd = File::Spec->catfile($epoc32path,"gcc","bin","cpp") . " $cppflags -D UNICODE $defines rom1.tmp rom2.tmp";
+} else {
+	$cppcmd = "cpp $cppflags $defines rom1.tmp rom2.tmp";
+}
+print "Executing CPP:\n\t$cppcmd\n" if $debug;
+$ret = system($cppcmd);
+die "ERROR EXECUTING CPP\n" if $ret;
+
+# Purge remarks and blank lines. Complete source filenames and adapt them to host filesystem.
+rectify("rom2.tmp", "rom3.tmp", $k);
+
+
+# scan tmp file and generate auxiliary files, if required
+open TMP, "rom3.tmp" or die("Can't open rom3.tmp\n");
+while ($line=<TMP>)
+	{
+	if ($line=~/\s*gentestpaged/i) {
+		genfile("paged");	}
+	if ($line=~/\s*gentestnonpaged/i) {
+		genfile("nonpaged");	}
+	}
+
+parsePatchData("rom3.tmp", "rom4.tmp");
+
+# break down the oby file into rom, rofs and extensions oby files
+
+my $oby_index =0;
+my $dumpfile="rom.oby";
+my $rofs=0;
+my $extension=0;
+my $corerofsname="";
+open DUMPFILE, ">$dumpfile" or die("Can't create $dumpfile\n");
+open TMP, "rom4.tmp" or die("Can't open rom4.tmp\n");
+while ($line=<TMP>)
+	{
+	if ($line=~/^\s*rofsname/i)
+		{
+		close DUMPFILE;							# close rom.oby or previous rofs#/extension#.oby
+		$oby_index=1;
+		$corerofsname=$line;
+		$corerofsname =~ s/rofsname\s*=\s*//i;		# save core rofs name
+		chomp($corerofsname);
+		unlink $corerofsname || print "unable to delete $corerofsname";
+		my $dumpfile="rofs".$rofs.".oby";
+		$rofs++;
+		open DUMPFILE, ">$dumpfile" or (close TMP and die("Can't create $dumpfile\n"));
+		}
+
+	if ($line=~/^\s*coreimage/i)
+		{
+		close DUMPFILE;							# close rofs.oby
+		if ($oby_index ne 1) {
+			close TMP;
+			die "Must specify ROFS image before ROFS extension\n";
+		}
+		my $name=$line;
+		$name =~ s/coreimage\s*=\s*//i;		# read core rofs name
+		chomp($name); 			# remove trailing \n
+		if ($name ne $corerofsname) {
+			close TMP;
+			die "This extension does not relate to previous ROFS\n";
+		}
+		$oby_index=33;						# open window
+		my $dumpfile="extension".$extension.".oby";
+		$extension++;
+		open DUMPFILE, ">$dumpfile" or (close TMP and die("Can't create $dumpfile\n"));
+		}
+
+	if ($line=~/^\s*extensionrofs/i)
+		{
+		$oby_index=3 if ($oby_index eq 2);
+		}
+
+	if (($oby_index eq 2) && !($line=~/^\s*$/)) {
+		close TMP;
+		die "Bad ROFS extension specification\n";
+	}
+	print DUMPFILE $line;
+	$oby_index=2 if ($oby_index eq 33);		# close window
+	}
+close DUMPFILE;
+close TMP;
+
+# For paged roms that use rofs, move all data= lines in rom which are not 'paging_unmovable' to rofs, so that paged ram-loaded code
+# is automatically put into rofs
+rename('rom.oby', 'rom4.tmp') || die;
+
+open(IN, 'rom4.tmp') || die "Can't read rom4.tmp";
+open(ROM, '>rom.oby') || die "Can't write to rom.oby";
+
+if ($oby_index >= 1 && $pagedCode)	{
+	open(ROFS, '>>rofs0.oby') || die "Can't append to rofs0.oby";
+}
+
+while ($line=<IN>)
+{
+	if(($oby_index >= 1) && ($pagedCode) && ($line=~/^\s*data\s*=/) && !($line=~/\.*paging_unmovable\s*/)) {
+		print ROFS $line;
+	}
+	else {
+		$line=~s/paging_unmovable//;
+		print ROM $line;
+	}
+}
+
+close IN;
+close ROM;
+
+if ($oby_index >= 1 && $pagedCode)	{
+	close ROFS;
+}
+	unlink 'rom4.tmp';
+
+my $flags;
+
+foreach (@{$flags{$opts{'assp'}}}) {
+	$flags.=" -$_";
+}
+
+if($opts{'noheader'}) {
+	$flags.=" -no-header";
+}
+
+if($opts{'compress'}) {
+	$flags.=" -compress";
+}
+
+my $builder = $opts{'rombuilder'};
+if ($on_windows) {
+	$builder = File::Spec->catfile($toolpath,"rombuild.exe") unless ($builder);
+}
+else {
+	$builder = File::Spec->catfile($toolpath,"rombuild") unless ($builder);
+	unless ( -x $builder ) {
+		chmod 0755,$builder;
+	}
+}
+
+print "$builder $flags -type-safe-link -S rom.oby 2>&1\n\n";
+
+open(Y, "$builder $flags -type-safe-link -S rom.oby 2>&1 | ") || 
+	die "Can't start $builder command, $!";
+
+my $nerrors=0;
+my $nwarnings=0;
+
+while(<Y>) {
+	my $error=(/^error:/i);
+	my $warning=(/^warning:/i);
+	print if ($error or $warning or !$quiet);
+	$nerrors++ if ($error);
+	$nwarnings++ if ($warning);
+}
+
+print "\nGenerated .oby file is rom.oby\n" if !$quiet;
+print "\nGenerated image file is $romname\n" if (!$nerrors);
+
+my$rerrors;
+my $rofsbuilder;
+if ($rofs) {
+	$rofsbuilder = $opts{'rofsbuilder'};
+	$rofsbuilder = "rofsbuild" unless ($rofsbuilder);
+	for(my $i=0;$i<$rofs;++$i) {
+		print "Executing $rofsbuilder on main rofs\n" if !$quiet;
+		my $image="rofs".$i.".oby";
+		system("$rofsbuilder $image");
+		if ($? != 0)
+			{
+			print "$rofsbuilder $image returned $?\n";
+			$rerrors++;
+			}
+		rename "rofsbuild.log", "rofs$i.log"
+		}
+}
+
+if ($rofs and $extension) {
+	for(my $i=0;$i<$extension;++$i) {
+		print "Executing $rofsbuilder on extension rofs\n" if !$quiet;
+		my $image="extension".$i.".oby";
+		system("$rofsbuilder $image");
+		if ($? != 0)
+			{
+			print "$rofsbuilder $image returned $?\n";
+			$rerrors++;
+			}
+		rename "rofsbuild.log", "extension$i.log"
+		}
+}
+
+if ($nerrors) {
+	print "\n\n Errors found during $builder!!\n\nLeaving tmp files\n";
+} elsif ($nwarnings) {
+	print "\n\n Warnings during $builder!!\n\nLeaving tmp files\n";
+} elsif ($rerrors) {
+	print "\n\n Errors during $rofsbuilder!!\n\nLeaving tmp files\n";
+} else {
+	unlink glob("*.tmp") if !$debug;
+}
+if ($opts{zip} or $zip{$opts{assp}}) {
+	my $zipname=$romname;
+	$zipname =~ s/\.(\w+)$/\.zip/i;
+	unlink $zipname;
+	system("zip $zipname $romname");
+}
+if ($opts{symbol}) {
+	my $logname=$romname;
+	$logname =~ s/\.(\w+)$/\.log/i;
+	my $obyname=$romname;
+	$obyname =~ s/\.(\w+)$/\.oby/i;
+	unlink $logname;
+	unlink $obyname;
+	system("rename rombuild.log $logname");
+	system("rename rom.oby $obyname");
+	system("maksym $logname");
+}
+
+#IMK if ($nerrors || $nwarnings || $rerrors) {
+#IMK	exit 4;
+#IMK}	
+if ($nerrors || $rerrors) {
+	exit 4;
+}	
+
+	
+exit 0;
+
+
+################################ Subroutines  ##################################
+
+sub usage {
+	print <<EOT;
+
+rom <options>
+
+Generate a rom image for the specified target, along with a rom.oby file
+that can be fed to (a) rombuild to regenerate the image.
+
+The following options are required:
+  --variant=<variant>         e.g. --variant=assabet
+  --inst=<instruction set>    e.g. --inst=arm4
+  --build=<build>             e.g. --build=udeb
+  --type=<type of rom>  
+         tshell for a text shell rom
+         e32tests for a rom with e32tests
+         f32tests for rom with f32tests
+         alltests for all the tests
+
+The following are optional:
+  --name=<image name>               Give image file specified name
+  --noheader                        Pass -no-header option on to rombuild
+  --help                            This help message.
+  --clean                           Remove existing generated files first
+  --quiet                           Be less verbose
+  --modules=<comma separated list>  List of additional modules for this ROM
+  --define=<comma separated list>   List of CPP macros to define
+
+Options may be specified as a short abbreviation 
+e.g. -b udeb instead of --build udeb
+
+EOT
+}
+
+sub rectify($$$) {
+	my ($in, $out, $k) = @_;
+	my $lastblank;
+	my $lineno = 0;
+
+	open(OUTPUT_FILE, "> $out") or die "Cannot open $out for output";
+	open(INPUT_FILE, "< $in") or die "Cannot open for $in input";
+  
+	while ($line=<INPUT_FILE>) {
+		++$lineno;
+		if ($line =~ /^\/\// ) {} # Ignore c++ commented lines.
+		elsif ($line =~ /^\s*REM\s+/i) {} # Ignore REM commented lines.
+		elsif ($line =~ /^\s*$/) { # Compress blank lines down to one
+			if($lastblank) {
+				# Do nothing
+			}
+			else {
+				# This is the first blank line
+				$lastblank=1;
+				print OUTPUT_FILE $line;
+			}
+		}
+		else {
+			# Not blank
+			$lastblank = 0;
+			$line =~ s|##||g; # Delete "token-pasting" ops
+			$line =~ s|//.*$||g; # Delete trailing c++ comments
+			# prefix the epocroot dir to occurrences of 'epoc32' in all "KEYWORD=..." lines.
+			$line =~ s/(=\s*)[\\\/]epoc32/\1${epocroot}epoc32/i;
+			if (!defined($1)) { # Not a keyword line.	
+				if ($k and $line=~/^\s*kerneltrace/i) {
+					$line = "kerneltrace $k\n";
+				}
+			}
+			elsif ($line =~ /^(\s*\S+\s*=\s*)(\S+)(\s*\S*)/) {
+				if ($on_windows) {
+					$line =~ s|\/|\\|g;
+				}
+				else {
+					my $keyword_part = $1;
+					my $src = $2;
+					my $dest = $3;
+					$src =~ s|\\|\/|g;
+					if ($dest) {
+						my ($vol,$dir,$leaf) = File::Spec->splitpath($src);
+						my $lc_leaf = lc($leaf);
+						my $lc_dir = lc($dir);
+						$lc_dir =~ s/\/$//;
+						my $fulldir = $lc_dir;
+						$fulldir =~ s|//|/|g;
+						unless ( -d $fulldir ) {
+							chomp $line;
+							# Lower-cased source directory doesn't exist. Give up.
+							die "Guessed source directory \"$fulldir\" does not exist for line $lineno: \"$line\"\n";
+						}
+						if (($leaf eq $lc_leaf) or (-f "$fulldir\/$leaf")) { 
+							# Using source directory lowercase and source filename as input.
+							$line = "${keyword_part}${lc_dir}\/${leaf}${dest}\n";
+						}
+						elsif ( -f "$fulldir\/$lc_leaf") {
+							# Using source directory source filename both lowercase.
+							$line = "${keyword_part}${lc_dir}\/${lc_leaf}${dest}\n";
+						}
+						else { # Harder.
+							my @dirlist;
+							my $found = 0;
+							if (!defined($dir_listings{$fulldir})) {
+								# Haven't got a cached dir listing for the source directory.
+								# Make one now.
+								@dirlist = glob("$fulldir.*");
+								$dir_listings{$fulldir} = \@dirlist;
+							}	
+							@dirlist = @{dir_listings{$fulldir}}; # Get listing of source directory from cache.
+							foreach my $file (@dirlist) {
+								# See if any file in the source directory case-insensitively matches the input source file.
+								if ( (-f "$fulldir\/$file") and (lc($file) eq $lc_leaf)) {
+									$line = "${keyword_part}${lc_dir}\/${file}${dest}\n";
+									$found = 1;
+									last;
+								}
+							}
+							unless ($found) {
+								die "Cannot find any file case-insensitively matching \"$fulldir\/$leaf\" at line $lineno: \"$line\"\n";
+							}
+						}
+					}						
+				} 
+			}
+			print OUTPUT_FILE $line;
+		}
+	}
+	close(INPUT_FILE);
+	close(OUTPUT_FILE);
+}
+
+sub IsRVCTBuild($) {
+    my ($build)=@_;
+    return 1 if ($build =~ /^ARMV/i);
+	my @customizations = Plat_Customizations('ARMV5');
+	return 1 if (grep /$build/, @customizations);
+	return 0;
+}
+
+
+sub IsSmp($) {
+	my %SmpKernelDirs=(
+		'x86smp' => 1,
+		'x86gmp' => 1,
+		'arm4smp' => 1,
+		'armv4smp' => 1,
+		'armv5smp' => 1
+	);
+
+	my ($kdir) = @_;
+	return $SmpKernelDirs{lc $kdir};
+}
+
+sub checkopts {
+	unless($opts{variant}) { die "No Variant specified"; }
+	$opts{'build'}="UDEB" unless($opts{'build'});
+	$opts{'type'}="TSHELL" unless($opts{'type'});
+	$opts{'inst'}="ARM4" unless($opts{'inst'});
+
+	my $additional;
+	if ($opts{'modules'}) {
+		$additional="_".$opts{modules};
+		$additional=~ s/,/_/ig;
+	}
+	my $build=lc $opts{build};
+	my $inst=uc $opts{'inst'};
+	if ($inst eq "MARM") {
+		# Hackery to cope with old compiler
+		$main="MARM";
+		$euserdir="MARM";
+		$elocldir="MARM";
+	}
+	else {
+		$main=$inst;
+		if ($main eq "THUMB") {
+			$euserdir="ARMI";
+		} else {
+			$euserdir=$main;
+		}
+		if ($main eq "ARMI" or $main eq "THUMB") {
+			$elocldir="ARM4";
+		} else {
+			$elocldir=$main;
+		}
+	}
+	$kmain = $opts{'xabi'};
+	$kmain = $main unless ($kmain);
+	if (IsSmp($kmain)) {
+		$euserdir = $kmain;
+	}
+	if ($opts{name}) {
+		$romname=$opts{name};
+	} else {
+		$romname=uc($opts{variant}.$additional.$main);
+		if ($build=~/^\w*DEB$/i) {
+			$romname.='D';
+		}
+		$romname.='.IMG';
+	}
+}
+
+sub lookupFileInfo($$)
+{
+	my ($infile, $fullname) = @_;
+
+	my ($name, $ext) = $fullname =~ /^(.+)\.(\w+)$/ ? ($1, $2) : ($fullname, undef);
+
+	open TMP, $infile or die("Can't open $infile\n");
+	while(<TMP>)
+	{
+		$_ = lc;
+		if(/^\s*(\S+)\s*=\s*(\S+)\s+(\S+)/i)
+		{
+			my ($src, $dest) = ($2, $3);
+
+			my $destFullname = $dest =~ /^.*\\(.+)$/ ? $1 : $dest;
+			my ($destName, $destExt) = $destFullname =~ /^(.+?)\.(\w+)$/ ? ($1, $2) : ($destFullname, undef);
+
+			if ($destName eq $name && (!$ext || $ext eq $destExt))
+			{
+				close TMP;
+				return ($src, $dest);
+			}
+		}
+	}
+
+	die "patchdata: Can't find file $fullname\n";
+}
+
+sub lookupSymbolInfo($$)
+{
+	my ($file, $name) = @_;
+
+	open TMP, $file or die "Can't read $file\n";
+
+	# ignore local symbols.
+	while (<TMP>)
+	{
+		last if /Global Symbols|Linker script and memory map/;
+	}
+
+  my @return_values = ();
+  my $line;
+	while ($line = <TMP>)
+	{
+		next if (index($line, $name) < 0);		
+		
+		# RVCT 2.2
+		# 
+		#     KHeapMinCellSize  0x0004e38c  Data 4  mem.o(.constdata)
+		#
+		if ($line =~ /^\s*(\S+)\s+(\S+)\s+data\s+(\S+)/i)
+		{
+			my ($symbol, $addr, $size) = ($1, $2, $3);
+			if ($symbol eq $name)
+			{
+				@return_values = ($addr, $size);
+				last;
+			}
+		}
+
+		# This is a quick fix for RVCT 3.1, which uses the text "(EXPORTED)"
+		# in the map file. Here is an example:
+		#
+		# KHeapMinCellSize (EXPORTED) 0x0003d81c Data 4 mem.o(.constdata)
+		#
+		elsif ($line =~ /^\s*(\S+)\s+\(exported\)\s+(\S+)\s+data\s+(\S+)/i)
+		{
+			my ($symbol, $addr, $size) = ($1, $2, $3);
+			if ($symbol eq $name)
+			{
+				@return_values = ($addr, $size);
+				last;
+			}
+		}
+		
+		# GCC 4.x map files
+		#                 0x00114c68                KHeapMinCellSize
+		#                 0x00114c6c                KHeapShrinkHysRatio
+		#  .rodata        0x00115130      0x968 M:/epoc32/build/kernel/c_99481fddbd6c6f58/_omap3530_ekern_exe/armv5/udeb/heap_hybrid.o
+		#
+		elsif ($line =~ /^.+\s+(0x\S+)\s+(\S+)/i)
+		{
+			my ($addr, $symbol) = ($1, $2);
+			if ($symbol eq $name)
+			{
+				my $next_line = <TMP>;
+				if ($next_line =~ /^.+\s+(0x\S+)\s+(\S+)/i)
+				{
+					my $addr2 = $1;
+					
+					@return_values = ($addr, hex($addr2) - hex($addr));
+					last;
+				}
+			}
+		}
+
+	}
+	close TMP;
+
+	die "patchdata: Can't find symbol $name\n" if (scalar @return_values == 0);
+	return @return_values;
+}
+
+sub parsePatchData($$)
+{
+	my ($infile, $outfile) = @_;
+
+	open IN, $infile or die("Can't read $infile\n");
+	open OUT, ">$outfile" or die("Can't write $outfile\n");
+
+	my $line;
+	while($line = <IN>)
+	{
+		if ($line =~ /^\s*patchdata\s+(.+?)\s*$/i)
+		{
+			if ($1 !~ /(\S+)\s*@\s*(\S+)\s+(\S+)\s*$/)
+			{
+				die "Bad patchdata command: $line\n";
+			}
+
+			my ($file, $symbol, $value) = (lc $1, $2, $3);
+			my ($srcFile, $destFile) = lookupFileInfo($infile, $file);
+			my ($index, $elementSize) = (undef, undef);
+			if ($symbol =~ s/:(\d+)\[(\d+)\]$//)
+			{
+				($index, $elementSize) = ($2, $1);
+				$index = hex($index) if $index =~ /^0x/i;
+			}
+
+			if ($srcFile =~ /\\armv5(smp)?\\/i)
+			{
+				my ($symbolAddr, $symbolSize) = lookupSymbolInfo("$srcFile.map", $symbol);
+
+				my $max;
+				if (defined($index))
+				{
+					my $bytes;
+					$bytes = 1, $max = 0xff       if $elementSize ==  8;
+					$bytes = 2, $max = 0xffff     if $elementSize == 16;
+					$bytes = 4, $max = 0xffffffff if $elementSize == 32;
+					die("patchdata: invalid element size $elementSize: $line\n") unless defined($bytes);
+
+					if ($bytes > 1 && (($symbolSize & ($bytes-1)) != 0))
+					{
+						die("patchdata: unexpected symbol size $symbolSize for array $symbol ($elementSize-bit elements)\n");
+					}
+
+					if ($index >= int($symbolSize / $bytes))
+					{
+						die("patchdata: index $index out of bounds for $symbol of $symbolSize bytes ($elementSize-bit elements)\n");
+					}
+
+					$symbolAddr = hex($symbolAddr) if $symbolAddr =~ /^0x/i;
+					$symbolAddr += $index * $bytes;
+					$symbolAddr = sprintf("0x%x", $symbolAddr);
+
+					$symbolSize = $bytes;
+				}
+				elsif ($symbolSize == 1) { $max = 0xff; }
+				elsif ($symbolSize == 2) { $max = 0xffff; }
+				elsif ($symbolSize == 4) { $max = 0xffffffff; }
+				else { die "patchdata: Unexpected symbol size $symbolSize for $symbol\n"; }
+
+				$value = hex($value) if $value =~ /^0x/i;
+				if ($value > $max)
+				{
+					print("Warning:  Value overflow of $symbol\n");
+					$value &= $max;
+				}					
+				$value = sprintf("0x%08x", $value);
+
+				$line = "patchdata $destFile addr $symbolAddr $symbolSize $value\n";
+			}
+			else
+			{
+				$line = "";
+			}
+
+		}
+
+		print OUT $line;
+	}
+
+	close IN;
+	close OUT;
+}
+
+sub genfile {
+	my $count=0;
+	if($_[0] eq 'paged') {
+		my $file='gentestpaged.txt';
+		unlink $file;
+		open(OUTFILE, ">$file") or die "Can't open output file, $!";
+		for(my $i=0;$i<50000;++$i) {
+			if(($i >5) && ($i % 40 ==0)) {
+			print OUTFILE "\n";
+			$count++;
+			} 
+			if(($i+$count) % 5 ==0) {
+			print OUTFILE "SATOR ";
+			}
+			if(($i+$count) % 5 ==1) {
+			print OUTFILE "AREPO ";
+			}
+			if(($i+$count) % 5 ==2) {
+			print OUTFILE "TENET ";
+			}
+			if(($i+$count) % 5 ==3) {
+			print OUTFILE "OPERA ";
+			}
+			if(($i+$count) % 5 ==4) {
+			print OUTFILE "ROTAS ";
+			}
+		}
+	} else {
+		my $file='gentestnonpaged.txt';
+		unlink $file;
+		open(OUTFILE, ">$file") or die "Can't open output file, $!";
+		for(my $i=0;$i<20000;++$i) {
+			if(($i >5) && ($i % 40 ==0)) {
+			print OUTFILE "\n";
+			$count++;
+			} 
+			if(($i+$count) % 4 ==0) {
+			print OUTFILE "STEP ";
+			}
+			if(($i+$count) % 4 ==1) {
+			print OUTFILE "TIME ";
+			}
+			if(($i+$count) % 4 ==2) {
+			print OUTFILE "EMIT ";
+			}
+			if(($i+$count) % 4 ==3) {
+			print OUTFILE "PETS ";
+			}
+		}
+	}
+}
+
+sub Variant_GetMacroHRHFile {
+	my $cfgFile =  File::Spec->catfile($toolpath,"variant","variant.cfg"); # default location
+	# save the volume, if any.
+	my ($cfg_vol,$ignore1,$ignore2) = File::Spec->splitpath($cfgFile);    
+    my $file;
+    if(-e $cfgFile){
+		open(FILE, $cfgFile) || die "\nCould not open for reading: " . $cfgFile ."\n";
+		while (<FILE>) {
+			# strip comments
+			s/^([^#]*)#.*$/$1/o;
+			# skip blank lines
+			if (/^\s*$/o) {
+				next;
+			}
+			# get the hrh file
+			if($_ =~ /\.hrh/xi){
+				$file = $_; 
+				last;
+			}
+		}
+		close FILE;
+		die "\nERROR: No variant file specified in $cfgFile!\n" unless $file;
+		$file =~ s/\s+//g;
+		$file =~ s|\\|\/|g, unless($on_windows);
+
+		if (File::Spec->file_name_is_absolute($file)) {
+			unless ( -f $file) {		
+			    $file = substr $file,1;                 
+				$file = File::Spec->catfile($epocroot,$file);
+			}	
+			my ($vol,$dir,$leaf) = File::Spec->splitpath($file);
+			die "\nERROR: Variant file specified in $cfgFile is not on the same volume as EPOCROOT\n", if (lc($vol) ne lc($cfg_vol));
+			#$file = File::Spec->catfile($dir,$file);
+		}
+		else {
+			$file = File::Spec->catfile($epoc32path,$file);
+		}
+
+		unless(-e $file) {
+			die "\nERROR: $cfgFile specifies $file which doesn't exist!\n";
+		}
+
+		$file =~ s/\//\\/g, if ($on_windows);
+    }
+    return $file;
+}
+