# MAKMAKE.PL
#
# Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
#


# all variables called *Path* are set up to end with a backslash
# all variables called *Path or *File are stored as absolute (file)paths within makmake
# all variables called UpPath* are stored as relative paths within makmake


my $PerlLibPath;

BEGIN {
# check user has a version of perl that will cope and use makmake as specified by the system path
	require 5.003_07;
	foreach (split ';', $ENV{Path}) {
		if (/^(\w:)?\\EPOC32\\TOOLS\\?$/io) {
			s-^(.*[^\\])$-$1\\-o;   # ensure path ends with a backslash
			$PerlLibPath=uc $_;
			last;
		}
	}
}


use lib $PerlLibPath;
use E32env;
use Genutl;
use Modload;
use Parsecom;
use Pathutl;

my %E32Env;
Env_Get(\%E32Env);


# THE MAIN PROGRAM SECTION
##########################

# PROCESS THE COMMAND LINE

Load_SetModulePath($PerlLibPath);

my %CLFlag;
my $MMPFILE;
my $Plat;

{
	# process the command line   V -> verbose, D -> default destination dir for makefile
	my @Flags=('Clean','D','MakeWork','Mmp','V');
	my @FlagArgs=();
	my @CLArgs;
	eval { &Com_ParseL(\%CLFlag,\@CLArgs,\@Flags,\@FlagArgs); };
	die $@ if $@;
	$CLFlag{'MakeMakeFile'}='1' unless ($CLFlag{'Clean'} || $CLFlag{'MakeWork'} || $CLFlag{'Mmp'});

	if ($CLFlag{V}) {
		print "PERL $PerlLibPath","MAKMAKE.PL @ARGV\n";
		&Load_SetVerbose;
		&Path_SetVerbose;
	}
	undef @ARGV;

	# test the command-line arguments 
	#--------------------------------
	if (@CLArgs!=2 || $CLFlag{Mmp}) {
		eval { &Load_ModuleL('MAKHELP'); };
		die $@ if $@; 
		if ($CLFlag{Mmp}) {
			if ($Plat=uc pop @CLArgs) {	# pop in case prj specified first
				eval { &Load_ModuleL($Plat); };
				die $@ if $@;
				&Help_Mmp($Plat);
				exit;
			}
			&Help_Mmp;
			exit;
		}
		eval { &Help_InvocationL; };
		die $@ if $@;
		exit;
	}

	$MMPFILE=uc shift @CLArgs;
	die "ERROR: Can't specify MMP file on a different drive\n" if $MMPFILE=~/^\w:\\/o;
	if ($MMPFILE!~/.MMP$/o) {
		$MMPFILE.=".MMP";
	}
	$MMPFILE=&Path_AbsToWork($MMPFILE);
	$Plat=uc shift @CLArgs;
}

# declare all variables the module may set here, if not already declared, before loading the module
my %PlatEnv;
@{$PlatEnv{'StdIncPaths'}}=();
$PlatEnv{'UserHdrsOnly'}='';

{
	# LOAD THE PLATFORM-SPECIFIC MODULE
	#----------------------------------
	eval { &Load_ModuleL($Plat); };
	die $@ if $@; 

	$Plat=uc &PMGetResetPlatName if defined &PMGetResetPlatName;
}

{
	# MMP FILE PROCESSING - filter the mmp file content through the GCC preprecessor
	#-------------------------------------------------------------------------------
	my @MmpMacros=($Plat);
	push @MmpMacros, &PMGetExtraMmpMacros if defined &PMGetExtraMmpMacros;
	eval { &Load_ModuleL('Mmp'); };
	die $@ if $@;

	if ($CLFlag{V}) {
		&Mmp_SetVerbose;
	}
	eval { &Mmp_ProcessL($MMPFILE,@MmpMacros); };
	die $@ if $@;
}

my %AifHash=&Mmp_AifHash;
my $AllowDllData=&Mmp_AllowDllData;
my $BaseFirstObj=&Mmp_BaseFirstObj;
my @BaseObjList=&Mmp_BaseObjList;
my %BitMapHash=&Mmp_BitMapHash;
my $CallDllEntryPoints=&Mmp_CallDllEntryPoints;
my $DataLinkAddress=&Mmp_DataLinkAddress;
my %Def=&Mmp_Def;
my %DocHash=&Mmp_DocHash;
my $FixedProcess=&Mmp_FixedProcess;
my %HeapSize=&Mmp_HeapSize;
my @LangList=&Mmp_LangList;
my @LibList=&Mmp_LibList;
my $LinkAs=&Mmp_LinkAs;
my $LongBldPath=&Mmp_LongBldPath;
my %MmpFlag=&Mmp_MmpFlag;
my @PlatTxt2D=&Mmp_PlatTxt2D;
my $ProcessPriority=&Mmp_ProcessPriority;
my $Prj=&Mmp_Prj;
my %ResrcHash=&Mmp_ResrcHash;
my %SrcHash=&Mmp_SrcHash;
my $StackSize=&Mmp_StackSize;    
my %SubPrjHash=&Mmp_SubPrjHash;
my @SysIncPaths=&Mmp_SysIncPaths;
my %SysResrcHash=&Mmp_SysResrcHash;
my $Trg=&Mmp_Trg;
my $TrgPath=&Mmp_TrgPath;
my $TrgType=&Mmp_TrgType;
my @UidList=&Mmp_UidList;
my @UnicodeUidList=&Mmp_UnicodeUidList;
my @UserIncPaths=&Mmp_UserIncPaths;

my @BldList;
my $CurBld;
my %DefBaseExtHash=();
my $GenTrgType;
my %MacroHash;
push @{$MacroHash{'Plat'}},$E32Env{OSMacro},$E32Env{OldOSMacro};
my $MakeFileExt=".$Plat"; # default

{
	# PLATFORM PROCESSING
	#--------------------
	# Request some initialisation data from the platform having read the mmpfile
	#---------------------------------------------------------------------------

	@BldList=&PMGetBldList;
	foreach (@BldList) {
		$_=uc $_;
	}

	# remove unicode builds from the buildlist unless narrow uids not specified either
	if ($UnicodeUidList[0]=~/^0x00000000$/o  && (not $UidList[0]=~/^0x00000000$/o)) {
		@BldList= grep /^[^U]/o, @BldList;
	}

	$MakeFileExt=uc &PMGetMakeFileExt if defined &PMGetMakeFileExt;
	$MakeFileExt=~s/^([^\.].*)$/\.$1/o;   # give the makefile extension a dot if it hasn't got one

	# 'MULTI' or 'SINGLE' for multi-process (eg MARM) or single-process (eg WINS) platforms respectively
	# initialise to 'MULTI'.
	my $PlatProcType='MULTI';
	$PlatProcType=uc &PMGetPlatProcType if defined &PMGetPlatProcType;
	GENTRGTYPE: {
		if ($TrgType=~/^(DLL|APP|FSY|LDD|PDD)$/o) {
			$GenTrgType='DLL'; last GENTRGTYPE;
		}
		if ($TrgType=~/^EXE$/o) {
			$GenTrgType='EXE'; last GENTRGTYPE;
		}
		if ($TrgType=~/^(LIB|IMPLIB)$/o) {
			$GenTrgType='LIB'; last GENTRGTYPE;
		}
		if ($TrgType=~/^EXEDLL$/o) {
			if ($PlatProcType=~/^SINGLE$/o) {
				$GenTrgType='DLL';
				if (&Path_Split('Ext',$Trg)=~/^(.EXE|)$/o) {
					$Trg=&Path_Split('Base',$Trg).'.DLL';
				}
				if (&Path_Split('Ext',$LinkAs)=~/^(.EXE|)$/o) {
					$LinkAs=&Path_Split('Base',$LinkAs).'.DLL';
				}
				last GENTRGTYPE;
			}
			if ($PlatProcType=~/^MULTI$/o) {
				$GenTrgType='EXE';
				$Trg=&Path_Split('Base',$Trg).'.EXE';
				$LinkAs=&Path_Split('Base',$Trg).'.EXE';
				last GENTRGTYPE;
			}
		}
		undef $GenTrgType;
	}
	undef $PlatProcType;

# set the first object basename
	$BaseFirstObj="E$GenTrgType" unless $BaseFirstObj;


	if ($GenTrgType=~/^EXE$/o or $TrgType=~/^EXEDLL$/o) {
		unshift @UidList, '0x1000007a';
	}
	elsif ($GenTrgType=~/^DLL$/o) {
		unshift @UidList, '0x10000079';
	}
	else {
		unshift @UidList, '0x00000000';
	}
	unshift @UnicodeUidList, $UidList[0]; # this is the same as the narrow build at the moment

	push @{$MacroHash{'Plat'}},&PMGetPlatMacroList;
	if ($GenTrgType=~/^DLL$/o) {
		push @{$MacroHash{'Plat'}},'__DLL__';
	}
	elsif ($GenTrgType=~/^EXE$/o) {
		push @{$MacroHash{'Plat'}},'__EXE__';
	}


	%DefBaseExtHash=&PMGetDefBaseExts;
	my $Entry;
	foreach $Entry (keys %DefBaseExtHash,values %DefBaseExtHash) {
		$Entry=uc $Entry;
	}

	my $LoopBld;	# always specify var for loops if calling module subroutine inside loop
	foreach $LoopBld (@BldList) {
		$CurBld=$LoopBld;
		@{$MacroHash{$CurBld}}=&PMGetBldMacroList;
		@{$MacroHash{$CurBld}}=() if not defined @{$MacroHash{$CurBld}};
		next unless ($MmpFlag{NoStrictDef} || (not defined $DefBaseExtHash{$CurBld}));
		$DefBaseExtHash{$CurBld}='';
	}


	if ($Def{Base} && !$Def{Path}) {
		$Def{Path}=uc &PMGetDefFilePath;
		$Def{Path}=~s-^([^\\].*)$-\\$1-o;
		$Def{Path}=~s-^(.*[^\\])$-$1\\-o;
	}

	undef $CurBld;
	undef $LoopBld;
}

my $MAKEFILE;

{
	# set up the makefile filepath
	#-----------------------------
	if (not $CLFlag{D}) {
		$MAKEFILE=join "", &Path_WorkPath,&Path_Split('Base',$MMPFILE),$MakeFileExt;
	}
	else {
		$MAKEFILE=join "", $E32Env{MakePath},$Plat,"\\",&Path_Split('Base',$MMPFILE),$MakeFileExt;
	}
}

{
	# get the platform module to do it's mmpfile processing
	#------------------------------------------------------
	&PMPlatProcessMmp if defined &PMPlatProcessMmp;
}

{
	# if clean flag set, clean all project's non-source files from the work directories then exit
	#--------------------------------------------------------------------------------------------
	if ($CLFlag{Clean}) {
		if ($CLFlag{V}) {
			print "Cleaning ...\n";
		}
		my $LoopBld;
		foreach $LoopBld (@BldList) {
			$CurBld=$LoopBld;
			&Path_DelFiles(&PMGetCleanFileList);
		}
		exit;
	}
}

{
	# if makework flag set, make the work directories then exit
	#----------------------------------------------------------
	if ($CLFlag{MakeWork}) {
		if ($CLFlag{V}) {
			print "Making Work Directories ...\n";
		}
		my $LoopBld;
		foreach $LoopBld (@BldList) {
			$CurBld=$LoopBld;
			eval { &Path_MakePathL(&PMGetWorkPathList); };
			die $@ if $@;
		}
		exit;
	}
}

{
	# if verbose mode set, output some info
	#--------------------------------------
	if ($CLFlag{V}) {
		print  
			"Project: \"$Prj\"\n",
			"Target: \"$Trg\"\n",
			"TargetType: \"$TrgType\"\n",
			"Libraries: \"@LibList\"\n",
			"Uids: \"@UidList\"\n",
			"UnicodeUids: \"@UnicodeUidList\"\n",
			"BuildVariants: \"@BldList\"\n",
			"TargetMakeFile: \"$MAKEFILE\"\n",
			"UserIncludes: \"<Source Dir> @UserIncPaths\"\n",
			"SystemIncludes: \"@SysIncPaths\"\n",
			"Objects: \"@BaseObjList\"\n",
			"Languages: \"@LangList\"\n"
		;
	}
	my $SP;
	my $BM;
	foreach $SP (keys %BitMapHash) {
		foreach $BM (keys %{$BitMapHash{$SP}}) {
			print "BitMap: \"$BM\"\n";
		}
	}
}

my $CurBaseObj;
my $CurBitMapTrg;
my @CurDepList;
my $CurDoc;
my $CurResrc;
my $CurSrc;
my $CurSubPrj;
my $ResrcIsSys;

{

	# LOOPING SECTION
	#----------------
# Load the output module
	eval { &Load_ModuleL('OUTPUT'); };
	die $@ if $@;

	&PMStartBldList if defined &PMStartBldList;
	my $LoopBld;
	foreach $LoopBld (@BldList) {
		$CurBld=$LoopBld;
		&PMBld if defined &PMBld;
	}
	undef $CurBld;
	undef $LoopBld;
	&PMEndBldList if defined &PMEndBldList;


	# Load the Dependency Generator
	eval { &Load_ModuleL('MAKDEPS'); };
	die $@ if $@;
	eval { &Deps_InitL($E32Env{GenHdrPath},@{$PlatEnv{'StdIncPaths'}}); };
	die $@ if $@;
	if ($CLFlag{'V'}) {
		&Deps_SetVerbose;
	}
	if ($PlatEnv{'UserHdrsOnly'}) {
		&Deps_SetUserHdrsOnly;
	}
	&Deps_SetUserIncPaths(@UserIncPaths);
	&Deps_SetSysIncPaths(@SysIncPaths);
	&Deps_SetPlatMacros(@{$MacroHash{'Plat'}});


	&PMStartSubPrjList if defined &PMStartSubPrjList;

# SubPrjLoopStart

	my $LoopSubPrj;
	foreach $LoopSubPrj (sort keys %SubPrjHash) {
		$CurSubPrj=$LoopSubPrj;
		if ($CLFlag{V}) {
			print "SubProject: \"$CurSubPrj\"\n";
		}
		&PMStartSubPrj if defined &PMStartSubPrj;

# SrcLoopStart

		my $LoopSrc;
		foreach $LoopSrc (sort @{$SrcHash{$CurSubPrj}}) {
			$CurSrc=$LoopSrc;
			if ($CLFlag{V}) {
				print "Source: \"$CurSrc\"\n";
			}
			&PMStartSubPrjSrc if defined &PMStartSubPrjSrc;

	# strict depend alt 1 start - call different module function if strict depend flag specified

			if (((not $MmpFlag{StrictDepend}) || (not defined &PMSubPrjSrcBldDepend)) && defined &PMSubPrjSrcDepend) {
				eval { @CurDepList=&Deps_GenDependsL($CurSubPrj.$CurSrc); };
				die $@ if $@;
				&PMSubPrjSrcDepend if defined &PMSubPrjSrcDepend;
				undef @CurDepList;
			}

	# strict depend alt 1 end

# BldLoopStart

			my $LoopBld;
			foreach $LoopBld (@BldList) {
				$CurBld=$LoopBld;
				&PMStartSubPrjSrcBld if defined &PMStartSubPrjSrcBld;

	# strict depend alt 2 start - call the module function that deals with dependencies generated for each build variant

				if ($MmpFlag{StrictDepend} && defined &PMSubPrjSrcBldDepend) {
					eval { @CurDepList=Deps_GenDependsL($CurSubPrj.$CurSrc,@{$MacroHash{$CurBld}}); };
					die $@ if $@;
					&PMSubPrjSrcBldDepend if defined &PMSubPrjSrcBldDepend;
					undef @CurDepList;
				}

	# strict depend alt 2 end

				&PMEndSubPrjSrcBld if defined &PMEndSubPrjSrcBld;
			}
			undef $CurBld;
			undef $LoopBld;

# BldLoopEnd

			&PMEndSubPrjSrc if defined &PMEndSubPrjSrc;
		}
		undef $CurSrc;
		undef $LoopSrc;

# SrcLoopEnd

# DocLoopBegin

		my $LoopDoc;
		foreach $LoopDoc (sort @{$DocHash{$CurSubPrj}}) {
			$CurDoc=$LoopDoc;
			if ($CLFlag{V}) {
				print "Document: \"$CurDoc\"\n";
			}
			&PMSubPrjDoc if defined &PMSubPrjDoc;
		}
		undef $CurDoc;
		undef $LoopDoc;

# DocLoopEnd

# ResrcLoopBegin

		$ResrcIsSys=2;	# first  loop for sys resources then for standard resources - standard ones may include headers from system ones
		do {
			$ResrcIsSys--;	# this isn't great.
			my @ResrcList;
			if ($ResrcIsSys) {
				@ResrcList=@{$SysResrcHash{$CurSubPrj}};
			}
			else {
				@ResrcList=@{$ResrcHash{$CurSubPrj}};
			}
			my $LoopResrc;
			foreach $LoopResrc (sort @ResrcList) {
				$CurResrc=$LoopResrc;
				if ($CLFlag{V}) {
					if ($ResrcIsSys) {
						print 'System';
					}
					print "Resource: \"$CurResrc\"\n";
				}
				&PMStartSubPrjResrc if defined &PMStartSubPrjResrc;
				if (defined &PMSubPrjResrcDepend) {
					eval { @CurDepList=&Deps_GenDependsL($CurSubPrj.$CurResrc); };
					die $@ if $@;
					&PMSubPrjResrcDepend if defined &PMSubPrjResrcDepend;
					undef @CurDepList;
				}

# BldLoopStart

				my $LoopBld;
				foreach $LoopBld (@BldList) {
					$CurBld=$LoopBld;
					&PMSubPrjResrcBld if defined &PMSubPrjResrcBld;
				}
				undef $CurBld;
				undef $LoopBld;

# BldLoopEnd

				&PMEndSubPrjResrc if defined &PMEndSubPrjResrc;
			}
			undef $CurResrc;
			undef $LoopResrc;
		} while ($ResrcIsSys);
		undef $ResrcIsSys;

# ResrcLoopEnd

# BitMapLoopBegin

		my $LoopBitMap;
		foreach $LoopBitMap (sort keys %{$BitMapHash{$CurSubPrj}}) {
			$CurBitMapTrg=$LoopBitMap;
			if ($CLFlag{V}) {
				print "BitMap: \"$CurBitMapTrg\"\n";
			}
			&PMStartSubPrjBitMapTrg if defined &PMStartSubPrjBitMapTrg;
				my $LoopBld;
				foreach $LoopBld (@BldList) {
					$CurBld=$LoopBld;
					&PMSubPrjBitMapTrgBld if defined &PMSubPrjBitMapTrgBld;
				}
				undef $CurBld;
				undef $LoopBld;
			&PMEndSubPrjBitMapTrg if defined &PMEndSubPrjBitMapTrg; 
		}
		undef $CurBitMapTrg;
		undef $LoopBitMap;

# BitMapLoopEnd


# AifLoopBegin

		if ($AifHash{'SubPrj'} && ($AifHash{'SubPrj'} eq $CurSubPrj)) {
			if ($CLFlag{V}) {
				print "Aif: \"$AifHash{'Aif'}\"\n";
			}
			&PMStartSubPrjAif if defined &PMStartSubPrjAif;
				my $LoopBld;
				foreach $LoopBld (@BldList) {
					$CurBld=$LoopBld;
					&PMSubPrjAifBld if defined &PMSubPrjAifBld;
				}
				undef $CurBld;
				undef $LoopBld;
			&PMEndSubPrjAif if defined &PMEndSubPrjAif; 
		}

# AifLoopEnd

		&PMEndSubPrj if defined &PMEndSubPrj;
	}
	undef $CurSubPrj;
	undef $LoopSubPrj;
	
# SubPrjLoopEnd

	&PMEndSubPrjList if defined &PMEndSubPrjList;
}


{
	eval { &Load_ModuleL('MAKSYS')};
	die $@ if $@; 

	# open the makefile and write all the text it requires to it if makmake has so far been successful
	#-------------------------------------------------------------------------------------------------
	eval { &Path_MakePathL($MAKEFILE); };
	die $@ if $@;
	if ($CLFlag{V}) {
		print "Creating: \"$MAKEFILE\"\n";
	}
	open MAKEFILE,">$MAKEFILE" or die "\nERROR: Can't open or create MakeFile \"$MAKEFILE\"\n";
	print MAKEFILE &Hack_TheOutput(&OutText) or die "\nERROR: Can't write output to MakeFile \"$MAKEFILE\"\n";
	close MAKEFILE or die "\nERROR: Can't close MakeFile \"$MAKEFILE\"\n";
	if ($CLFlag{V}) {
		print "Successful MakeFile Creation\n";
	}
}

	
################ END OF MAIN PROGRAM SECTION #################
#------------------------------------------------------------#
##############################################################





# SUBROUTINE SECTION
####################

sub CreateExtraFile ($$) { # takes abs path for source and text
# allows modules to create extrafiles
	my ($FILE,$Text)=@_;
	if ($CLFlag{MakeMakeFile}) {	# only create if making the makefile
		if ($CLFlag{V}) {
			print "Creating \"$FILE\"\n";
		}
		eval { &Path_MakePathL($FILE); };
		die $@ if $@;
		open FILE, ">$FILE" or die "WARNING: Can't open or create \"$FILE\"\n";
		print  FILE $Text or die "WARNING: Can't write text to \"$FILE\"\n";
		close FILE or die "WARNING: Can't close \"$FILE\"\n";
	}
}
sub AddSrc ($$) { # needs abs path for source
# allows modules to add a source file to the project and have it created if necessary
	my ($SRCFILE,$Text)=@_;
	my $SubPrj=&Path_Split('Path',$SRCFILE);
	if ((not -e $SRCFILE) || (-M $SRCFILE > -M $MMPFILE)) {
		# only create the file if it's older than the .MMP file
		CreateExtraFile($SRCFILE,$Text);
	}
	@{$SubPrjHash{$SubPrj}}=();
	push @{$SrcHash{$SubPrj}}, &Path_Split('File',$SRCFILE);
	@{$DocHash{$SubPrj}}=() unless defined @{$DocHash{$SubPrj}};
	@{$ResrcHash{$SubPrj}}=() unless defined @{$ResrcHash{$SubPrj}};
	@{$SysResrcHash{$SubPrj}}=() unless defined @{$SysResrcHash{$SubPrj}};
}
sub AddPlatMacros (@) {
# allows modules to add extra macros to the platform macro list
	push @{$MacroHash{'Plat'}},@_;
}
sub Aif () {
	$AifHash{Aif};
}
sub AllowDllData () {
	$AllowDllData;
}
sub BaseFirstObj () {
	$BaseFirstObj;
}
sub BaseLangMacro () {
	$E32Env{BaseLangMacro};
}
sub BaseObjList () {
	@BaseObjList;
}
sub BaseMak () {
	&Path_Split('Base',$MAKEFILE);
}
sub BaseResrc () {
	&Path_Split('Base',$CurResrc);
}
sub BaseResrcList () {
	my @ResrcList=&ResrcList;
	my $Path;
	foreach $Path (@ResrcList) {
		$Path=&Path_Split('Base',$Path);
	}
	@ResrcList;
}
sub BaseSrc () {
	&Path_Split('Base',$CurSrc);
}
sub BaseSrcList () {
	my @SrcList=&SrcList;
	my $Path;
	foreach $Path (@SrcList) {
		$Path=&Path_Split('Base',$Path);
	}
	@SrcList;
}
sub BaseSysResrcList () {
	my @SysResrcList=&SysResrcList;
	my $Path;
	foreach $Path (@SysResrcList) {
		$Path=&Path_Split('Base',$Path);
	}
	@SysResrcList;
}
sub BaseTrg () {
	&Path_Split('Base',$Trg);
}
sub BitMapSrcList () {
	sort @{$BitMapHash{$CurSubPrj}{$CurBitMapTrg}};
}
sub BitMapTrg () {
	$CurBitMapTrg;
}
sub BitMapTrgList () {
	if ($CurSubPrj) {
		return keys %{$BitMapHash{$CurSubPrj}};
	}
	my @BMList;
	my $Key;
	foreach $Key (keys %BitMapHash) {
		push @BMList, keys %{$BitMapHash{$Key}};
	}
	sort @BMList;
}
sub Bld () {
	$CurBld;
}
sub BldList () {
	@BldList;
}
sub BldPath () {
	my $BldPath=$E32Env{BldPath}."$Prj\\";
	if ($LongBldPath) {
		$BldPath.="$LongBldPath\\";
	}
	$BldPath.=$Plat;
	if ($GenTrgType=~/^(DLL|LIB)$/o) {
		$BldPath.="D";
	}
	$BldPath.="\\";
	if ($CurBld) {
		$BldPath.="$CurBld\\";
	}
	$BldPath;
}
sub CallDllEntryPoints () {
	$CallDllEntryPoints;
}
sub DataLinkAddress () {
	$DataLinkAddress;
}
sub DataPath () {
	$E32Env{DataPath};
}
sub DefFile () {
	# need if clause because $DefBaseExtHash{$CurBld} may be set whether component frozen or not
	return "$Def{Path}$Def{Base}$DefBaseExtHash{$CurBld}$Def{Ext}" if $Def{Base};
	'';
}
sub DefBaseExt () {
	"$DefBaseExtHash{$CurBld}";
}
sub DepList () {
	sort @CurDepList;
}
sub Doc () {
	$CurDoc;
}
sub DocList () {
	if ($CurSubPrj) {
		return sort @{$DocHash{$CurSubPrj}};
	}
	my @DocList;
	my $Key;
	foreach $Key (keys %DocHash) {
		push @DocList,@{$DocHash{$Key}};
	}
	sort @DocList;
}
sub FixedProcess () {
	$FixedProcess;
}
sub GenHdrPath () {
	$E32Env{GenHdrPath};
}
sub GenTrgType () {
	$GenTrgType;
}
sub HeapSize () {
	%HeapSize;
}
sub LangList () {
	@LangList;
}
sub LibList () {
	@LibList;
}
sub LinkAs () {
	$LinkAs;
}
sub MacroList ($) {
	if ($_[0]) {
	return @{$MacroHash{"$_[0]"}};
	}
	return @{$MacroHash{'Plat'}} unless $CurBld;
	(@{$MacroHash{'Plat'}},@{$MacroHash{"$CurBld"}});
}
sub MakeFilePath () {
	&Path_Split('Path',$MAKEFILE);
}
sub MmpFile () {
	$MMPFILE;
}
sub Plat () {
	$Plat;
}
sub PlatTxt () {
	@PlatTxt2D;
}
sub ProcessPriority () {
	$ProcessPriority;
}
sub Prj () {
	$Prj;
}
sub RelPath () {
	my $RelPath="$E32Env{RelPath}$Plat\\";
	if ($CurBld) {
		$RelPath.="$CurBld\\";
	}
	$RelPath;
}
sub Resrc () {
	$CurResrc;
}
sub ResrcHdr () {
	join '',$E32Env{'GenHdrPath'},&Path_Split('Base',$CurResrc),'.RSG';
}
sub ResrcList () {
	if ($CurSubPrj) {
		return @{$ResrcHash{$CurSubPrj}};
	}
	my @ResrcList;
	my $Key;
	foreach $Key (keys %ResrcHash) {
		push @ResrcList,@{$ResrcHash{$Key}};
	}
	sort @ResrcList;
}
sub	SetStdIncPaths (@) {
# allows module to set standard include paths
	@{$PlatEnv{'StdIncPaths'}}=();
	my $Path;
	foreach $Path (@_) {
		$Path=uc $Path;
		$Path=~s-^(.*[^\\])$-$1\\-o;
		push @{$PlatEnv{'StdIncPaths'}}, $Path;	# only place drive letters may appear, up to modules to handle
	}
}
sub SetUserHdrsOnly () {
# allows module to specify it requires user headers only
	$PlatEnv{'UserHdrsOnly'}=1;
}
sub Src () {
	$CurSrc;
}
sub SrcList () {
	if ($CurSubPrj) {
		return sort @{$SrcHash{$CurSubPrj}};
	}
	my @SrcList;
	my $Key;
	foreach $Key (keys %SrcHash) {
		push @SrcList,@{$SrcHash{$Key}};
	}
	sort @SrcList;
}
sub StackSize () {
	$StackSize;
}
sub SubPrj () {
	$CurSubPrj;
}
sub SysDefDir () {
	"$E32Env{'RelPath'}$Plat\\";
}
sub SysIncPaths () {
	@SysIncPaths;
}
sub SysResrcList () {
	if ($CurSubPrj) {
		return sort @{$SysResrcHash{$CurSubPrj}};
	}
	my @SysResrcList;
	my $Key;
	foreach $Key (keys %SysResrcHash) {
		push @SysResrcList,@{$SysResrcHash{$Key}};
	}
	sort @SysResrcList;
}
sub ResrcIsSys () {
	$ResrcIsSys;
}
sub Trg () {
	$Trg;
}
sub TrgPath () {
	$TrgPath;
}
sub TrgType () {
	$TrgType;
}
sub UidList () {
	@UidList;
}
sub UnicodeUidList () {
	@UnicodeUidList;
}
sub UserIncPaths () {
	@UserIncPaths;
}

