# 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:
# Processes an mmp file and sets up subroutines to return the data
#
#
package Mmp;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(
Mmp_SetVerbose
Mmp_ProcessL
Mmp_ABI
Mmp_AifStruct
Mmp_AllowDllData
Mmp_CompressTarget
Mmp_ASSPExports
Mmp_ASSPLibList
Mmp_BuildAsARM
Mmp_BitMapStruct
Mmp_CallDllEntryPoints
Mmp_Capability
Mmp_CapabilityFlags
Mmp_DataLinkAddress
Mmp_DebugLibList
Mmp_Def
Mmp_DocHash
Mmp_ExportUnfrozen
Mmp_FirstLib
Mmp_FixedProcess
Mmp_HeapSize
Mmp_LibList
Mmp_LinkAs
Mmp_LinkAsBase
Mmp_ExportLibrary
Mmp_NewLib
Mmp_NoExportLibrary
Mmp_Macros
Mmp_MmpFlag
Mmp_PlatTxt2D
Mmp_ProcessPriority
Mmp_ResourceStruct
Mmp_SmpSafe
Mmp_RamTargets
Mmp_RomTargets
Mmp_SourceStruct
Mmp_StackSize
Mmp_StatLibList
Mmp_SysIncPaths
Mmp_Trg
Mmp_TrgType
Mmp_UidList
Mmp_UserIncPaths
Mmp_SrcDbg
Mmp_StdCpp
Mmp_NoStdCpp
Mmp_WarningLevel
Mmp_LinkerOptions
Mmp_Reset
Mmp_Uids
Mmp_Version
Mmp_SecureId
Mmp_VendorId
Mmp_Replace
Mmp_ARMFPU
Mmp_SetIgnoreMissingDef
Mmp_StringTable
Mmp_CompressTargetMode
Mmp_CodePagingTargetMode
Mmp_DataPagingTargetMode
Mmp_CheckSourceMMPMetaData
Mmp_CheckSourceMMPIncludes
Mmp_IsWideCharMain
Mmp_IsDebuggable
Mmp_IsFeatureVariant
Mmp_TestedMacros
);
use strict;
use Genutl;
use Prepfile;
use Pathutl;
use Trgtype;
use CheckSource;
use Cwd;
my %ProcessPriorityNames = (
LOW=>'Low',
BACKGROUND=>'Background',
FOREGROUND=>'Foreground',
HIGH=>'High',
WINDOWSERVER=>'WindowServer',
FILESERVER=>'FileServer',
REALTIMESERVER=>'RealTimeServer',
SUPERVISOR=>'SuperVisor'
);
my %CapabilityNames;
my %Mode;
my $ABI;
my @AifStruct;
my $AllowDllData=0;
use constant COMPRESS => 0;
use constant NOCOMPRESS => 1;
my $CompressTarget=COMPRESS; # compress the target binary (negative logic)
use constant NOCOMPRESSIONMETHOD => 0;
use constant INFLATECOMPRESSIONMETHOD => 1;
use constant BYTEPAIRCOMPRESSIONMETHOD => 2;
my $CompressTargetMethod=NOCOMPRESSIONMETHOD; #NONE
my $ASSPABISwitch=0;
my $ASSPExports=0;
my @ASSPLibList;
my @BitMapStruct;
my $BuildAsARM=0;
my $CallDllEntryPoints=0;
my $Capability;
my @CapabilityFlags=(0,0);
my %CurSource;
my $DataLinkAddress='';
my @DebugLibList;
my %Def;
$Def{Path}='';
$Def{Base}='';
$Def{Ext}='';
my %DocHash;
my $ExportUnfrozen=0;
my $FirstLib;
my $FixedProcess=0;
my %HeapSize;
my @LangList;
my @LibList;
my $LinkAs;
my $LinkAsBase;
my $ExportLibrary;
my $NoExportLibrary;
my @Macros;
my %MmpFlag;
my $NewLib;
my @PlatTxt2D;
my $ProcessPriority='';
my @ResourceStruct;
my @RamTargets;
my @RomTargets=({}); # include default
my $SmpSafe = 0;
my @SourceStruct;
my $StackSize='';
my @StatLibList;
my $StdCpp = 0;
my $NoStdCpp = 0;
my @SysIncPaths;
my $Trg;
my %TrgType;
my @UidList;
my @UserIncPaths;
my $SrcDbg=0;
my %Compiler;
my %LinkerOptions;
my %Version;
my $SecureId;
my $VendorId;
my %Replace;
my $ARMFPU;
my $IgnoreMissingDef=0;
my @StringTableStruct;
my $CodePagingTargetMode; # 0-N/A, 1-UNPAGED, 2-PAGED
my $DataPagingTargetMode; # 0-N/A, 1-UNPAGED, 2-PAGED
my $WideCharMain=0;
my $IsDebuggable; # 0-NON_DEBUGGABLE, 1-DEBUGGABLE,2-DEBUGGABLE_UDEBONLY
my $FeatureVariant=0;
use constant NOTPAGED => 0;
use constant UNPAGED => 1;
use constant PAGED => 2;
use constant NON_DEBUGGABLE => 0;
use constant DEBUGGABLE => 1;
use constant DEBUGGABLE_UDEBONLY => 2;
my %CheckSourceMMPMetaData;
my %CheckSourceMMPIncludes;
my %mmptestedMacrosHash;
# List of deprecated 2nd UIDs. These are checked in a Secure Platform
my %deprecatedUIDs=
(
"0x10005e32" => "Unmigrated FEP detected from use of UID 0x10005e32 ",
"0x10004cc1" => "Unmigrated Application Initaliser (CEikLibrary deriver) detected from use of UID 0x10004cc1 ",
"0x10003a30" => "Unmigrated Conarc plugin detected from use of UID 0x10003a30",
"0x10003a19" => "Unmigrated Recogniser detected from use of UID 0x10003a19",
"0x10003a37" => "Unmigrated Recogniser detected from use of UID 0x10003a37",
"0x10003a34" => "Unmigrated CTL detected from use of UID 0x10003a34"
);
sub Mmp_Reset() {
undef $ABI;
undef @AifStruct;
$AllowDllData=0;
$CompressTarget=COMPRESS;
$CompressTargetMethod=NOCOMPRESSIONMETHOD;
$ASSPABISwitch=0;
$ASSPExports=0;
$BuildAsARM=0;
undef @ASSPLibList;
undef @BitMapStruct;
$CallDllEntryPoints=0;
undef $Capability;
@CapabilityFlags=(0,0);
undef $VendorId;
$DataLinkAddress='';
undef @DebugLibList;
undef %Def;
$Def{Path}='';
$Def{Base}='';
$Def{Ext}='';
undef %DocHash;
$ExportUnfrozen=0;
undef $FirstLib;
$FixedProcess=0;
undef %HeapSize;
undef @LangList;
undef @LibList;
undef $LinkAs;
undef $LinkAsBase;
undef $ExportLibrary;
undef @Macros;
undef %MmpFlag;
undef $NewLib;
undef @PlatTxt2D;
$ProcessPriority='';
undef @ResourceStruct;
undef @RamTargets;
@RomTargets=({}); # include default
undef @SourceStruct;
$StackSize='';
undef @StatLibList;
$SmpSafe = 0;
$StdCpp = 0;
$NoStdCpp = 0;
undef @SysIncPaths;
undef $Trg;
undef %TrgType;
undef @UidList;
undef @UserIncPaths;
$SrcDbg=0;
undef %Compiler;
undef %LinkerOptions;
undef %Version;
$IgnoreMissingDef=0;
undef $ARMFPU;
undef @StringTableStruct;
$CodePagingTargetMode=0; # default N/A
$DataPagingTargetMode=0; # default N/A
$IsDebuggable=0; # Default = 0 (Not debuggable)
undef %mmptestedMacrosHash;
}
BEGIN {
$Mode{'Verbose'}=0;
%CapabilityNames = (
TCB => (1<<0),
COMMDD => (1<<1),
POWERMGMT => (1<<2),
MULTIMEDIADD => (1<<3),
READDEVICEDATA => (1<<4),
WRITEDEVICEDATA => (1<<5),
DRM => (1<<6),
TRUSTEDUI => (1<<7),
PROTSERV => (1<<8),
DISKADMIN => (1<<9),
NETWORKCONTROL => (1<<10),
ALLFILES => (1<<11),
SWEVENT => (1<<12),
NETWORKSERVICES => (1<<13),
LOCALSERVICES => (1<<14),
READUSERDATA => (1<<15),
WRITEUSERDATA => (1<<16),
LOCATION => (1<<17),
SURROUNDINGSDD => (1<<18),
USERENVIRONMENT => (1<<19),
#old capability names have zero value
ROOT => 0,
MEDIADD => 0,
READSYSTEMDATA => 0,
WRITESYSTEMDATA => 0,
SOUNDDD => 0,
UIDD => 0,
KILLANYPROCESS => 0,
DEVMAN => 0,
PHONENETWORK => 0,
LOCALNETWORK => 0
);
my $all=0;
foreach (keys %CapabilityNames)
{
$all = $all | $CapabilityNames{$_};
}
$CapabilityNames{"ALL"} = $all;
}
sub Mmp_SetVerbose () {
$Mode{'Verbose'}=1;
}
sub Mmp_SetIgnoreMissingDef() {
$IgnoreMissingDef = 1;
}
sub Mmp_ProcessL ($$$$) {
my ($EPOCPath, $MMPFILE, $Plat_ref, $BuildIncList)=@_;
my $emulator = $$Plat_ref{OS} ne 'EPOC32';
if ($Mode{Verbose}) {
&Prepfile_SetVerbose;
}
# Generate macro usage information and add variant build includes
my $options = '-dU';
foreach ( @$BuildIncList )
{
$options .= ' -I ' . &Path_PrefixWithDriveAndQuote($_);
}
# preprocess the project description file
my @Mmp2D;
Prepfile_SetCmdOptions($options);
eval { &Prepfile_ProcessL(\@Mmp2D, $MMPFILE, &main::VariantFile(), @{$$Plat_ref{MmpMacros}}); };
Prepfile_SetCmdOptions('');
die $@ if $@;
my @checkSourceMacros;
foreach (@{$$Plat_ref{MmpMacros}}) {
$_=uc $_;
push @checkSourceMacros, " $_=_____$_";
}
my $current = cwd;
$current =~ s/\//\\/g;
$current =~ s/^[a-zA-Z]://;
# Mimic what the current parsing routine does in terms of include paths and .mmp files
my @checkSourceUserIncludePaths;
push @checkSourceUserIncludePaths, "$ENV{EPOCROOT}epoc32\\include";
push @checkSourceUserIncludePaths, "\.";
push @checkSourceUserIncludePaths, $current;
my @checkSourceSystemIncludePaths = ();
CheckSource_Includes($MMPFILE, %CheckSourceMMPIncludes, &main::VariantFile(), @checkSourceMacros, @checkSourceUserIncludePaths, @checkSourceSystemIncludePaths, $CheckSource_NoUserSystemDistinction);
my $NoStrictDef=0;
my $TrgPath='';
my $TrgType;
my $MmpPath=&Path_Split('Path', $MMPFILE);
my @MmpDie=();
my @MmpWarn=();
my @MmpDiagnostic=();
my @MmpMigrationNote=();
my (%CheckAif, %CheckASSPLib, %CheckDoc, %CheckLang, %CheckLib, %CheckMacro, %CheckResrc, %CheckSrc, %CheckStatLib, %CheckSysInc, %CheckSysResrc, %CheckUserInc);
my ($CheckDef);
my ($CheckRamTargets, $CheckRomTargets);
my ($OtherPlatSwitch, $PlatTxtSwitch);
my (%CurBitMap, $CurBitMapSrcPath);
$CurBitMapSrcPath=$MmpPath;
my (%CurResource, %ResourceCheckLang);
my %CurStringTable;
my ($CurSrcPath, $MmpMacro, $Line);
$CurSrcPath=$MmpPath;
# include the .MMP file as a document
@{$DocHash{$MmpPath}}=(&Path_Split('File', $MMPFILE));
$CheckDoc{$MMPFILE}='zero - specified by default';
# process the data structure
my $CurFile=$MMPFILE;
LINE: foreach $Line (@Mmp2D) {
my $LineNum=shift @$Line;
$_=shift @$Line;
if ($LineNum eq '#') {
$CurFile=$_;
next LINE;
}
# Get details of tested macros affecting the MMP file
# We get this from -dU preprocessor option
if (/^#define$/ && "@$Line" =~ /^(\w+(?:\([^\)]*\))?)(?:\s(\S.*?))?\s*$/)
{
# Record macro details for defined tested macro
$mmptestedMacrosHash{$1} = $2 ? "\'$2\'" : 'defined';
next LINE;
}
elsif (/^#undef$/)
{
# Record macro details for undefined tested macro
$mmptestedMacrosHash{"@$Line"} = 'undefined';
next LINE;
}
$CurFile = &Path_Norm ($CurFile);
$_=uc $_;
my $mainElement = $_;
if ($PlatTxtSwitch) {
if (/^END$/o) {
$PlatTxtSwitch=0;
next LINE;
}
push @PlatTxt2D, [ "$CurFile($LineNum)", $_, @$Line ];
next LINE;
}
if ($OtherPlatSwitch) {
if (/^END$/o) {
$OtherPlatSwitch=0;
next LINE;
}
next LINE;
}
# ----------- handle body of START BITMAP ... END -------------
if (%CurBitMap) {
if (/^SOURCE$/o) {
unless (@$Line>1) {
push @MmpDie, "$CurFile($LineNum) : Not enough arguments for Bitmap keyword SOURCE\n";
}
my $cldepth = shift @$Line;
my @ClDepths = split(/,/, $cldepth);
foreach (@ClDepths) {
$_ = lc $_; # bmconv can't handle upper-case 'C's
unless (/^c?\d\d?a?$/o) {
push @MmpDie, "$CurFile($LineNum) : BITMAP color depth \"$_\" - unexpected format\n";
}
}
@ClDepths = (@ClDepths) x @$Line; # make a sufficiently long list of color depths
foreach (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "BITMAP SOURCE", $_, $LineNum, $CheckSource_PhysicalCheck, $CurBitMapSrcPath);
$_ = &Path_Norm($_);
$_=lc $_; # bmconv generates a header with case-sensitive enums
my $bitmap = "$CurBitMapSrcPath$_";
push @{$CurBitMap{Source}}, { # sources must be kept in order
Src=>$bitmap,
ClDepth=>shift @ClDepths # take next color depth from the list
};
unless (-e $bitmap) {
push @MmpWarn, "$CurFile($LineNum) : BITMAP source \"$CurBitMapSrcPath$_\" not found\n";
}
}
next LINE;
}
if (/^END$/o) {
$CurBitMapSrcPath=$MmpPath;
my %BitMap=%CurBitMap;
undef %CurBitMap;
push @BitMapStruct, \%BitMap;
next LINE;
}
if (/^SOURCEPATH$/o) {
unless ($CurBitMapSrcPath=shift @$Line) {
push @MmpDie, "$CurFile($LineNum) : No path specified with Bitmap keyword SOURCEPATH\n";
next LINE;
}
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "BITMAP SOURCEPATH", $CurBitMapSrcPath, $LineNum, $CheckSource_PhysicalCheck);
$CurBitMapSrcPath = &Path_Norm($CurBitMapSrcPath);
$CurBitMapSrcPath=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$CurBitMapSrcPath=&Path_MakeAbs($CurFile,$CurBitMapSrcPath);
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for Bitmap keyword SOURCEPATH\n";
}
next LINE;
}
if (/^HEADER$/o) {
if ($CurBitMap{Hdr}) {
push @MmpWarn, "$CurFile($LineNum) : Bitmap HEADER already specified at line $CurBitMap{Hdr}\n";
next LINE;
}
$CurBitMap{Hdr}="$CurFile($LineNum)";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Bitmap keyword HEADER takes no arguments\n";
}
next LINE;
}
if (/^TARGETPATH$/o) {
if ($CurBitMap{TrgPath}) {
push @MmpWarn, "$CurFile($LineNum) : Bitmap TARGETPATH already specified\n";
next LINE;
}
unless ($CurBitMap{TrgPath}=shift @$Line) {
push @MmpDie, "$CurFile($LineNum) : No path specified with Bitmap keyword TARGETPATH\n";
next LINE;
}
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "BITMAP TARGETPATH", $CurBitMap{TrgPath}, $LineNum);
$CurBitMap{TrgPath} = &Path_Norm($CurBitMap{TrgPath});
$CurBitMap{TrgPath}=~s-^\\(.*)$-$1-o; # remove leading backslash, if any
$CurBitMap{TrgPath}=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$CurBitMap{TrgPath}="z\\$CurBitMap{TrgPath}";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for Bitmap keyword TARGETPATH\n";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Unrecognised Bitmap Keyword \"$_\"\n";
}
# ----------- handle body of START RESOURCE ... END -------------
if (%CurResource) {
if (/^END$/o) {
$CurResource{SrcPath}=$CurSrcPath;
my %Resource=%CurResource;
undef %CurResource;
push @ResourceStruct, \%Resource;
undef %ResourceCheckLang;
next LINE;
}
if (/^HEADER$/o) {
if ($CurResource{Hdr}) {
push @MmpWarn, "$CurFile($LineNum) : Resource HEADER already specified at line $CurResource{Hdr}\n";
next LINE;
}
elsif ($CurResource{Hdronly}) {
push @MmpWarn, "$CurFile($LineNum) : Resource HEADERONLY already specified at line $CurResource{Hdr}\n";
next LINE;
}
$CurResource{Hdr}="$CurFile($LineNum)";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Resource keyword HEADER takes no arguments\n";
}
next LINE;
}
if (/^HEADERONLY$/o) {
if ($CurResource{Hdronly}) {
push @MmpWarn, "$CurFile($LineNum) : Resource HEADERONLY already specified at line $CurResource{Hdr}\n";
next LINE;
}
elsif ($CurResource{Hdr}) {
push @MmpWarn, "$CurFile($LineNum) : Resource HEADER already specified at line $CurResource{Hdr}\n";
next LINE;
}
$CurResource{Hdronly}="$CurFile($LineNum)";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Resource keyword HEADERONLY takes no arguments\n";
}
next LINE;
}
if (/^LANG$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
if ($ResourceCheckLang{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Language \"$Candidate\" at line $ResourceCheckLang{$Candidate}\n";
next;
}
push @{$CurResource{Lang}}, $Candidate;
$ResourceCheckLang{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Languages specified for keyword LANG\n";
next LINE;
}
if (/^TARGET$/o) {
if ($CurResource{BaseTrg}) {
push @MmpWarn, "$CurFile($LineNum) : Resource TARGET already specified\n";
next LINE;
}
my $src=shift @$Line;
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "RESOURCE TARGET", $src, $LineNum);
$src = &Path_Norm($src);
$CurResource{BaseTrg}=&Path_Split('Base',$src);
unless ($CurResource{BaseTrg}) {
push @MmpDie, "$CurFile($LineNum) : No name specified with Resource keyword TARGET\n";
next LINE;
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for Resource keyword TARGET\n";
}
next LINE;
}
if (/^TARGETPATH$/o) {
if ($CurResource{TrgPath}) {
push @MmpWarn, "$CurFile($LineNum) : Resource TARGETPATH already specified\n";
next LINE;
}
unless ($CurResource{TrgPath}=shift @$Line) {
push @MmpDie, "$CurFile($LineNum) : No path specified with Resource keyword TARGETPATH\n";
next LINE;
}
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "RESOURCE TARGETPATH", $CurResource{TrgPath}, $LineNum);
$CurResource{TrgPath} = &Path_Norm($CurResource{TrgPath});
$CurResource{TrgPath}=~s-^\\(.*)$-$1-o; # remove leading backslash, if any
$CurResource{TrgPath}=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$CurResource{TrgPath}="z\\$CurResource{TrgPath}";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for Resource keyword TARGETPATH\n";
}
next LINE;
}
if (/^UID$/o) {
if (@$Line) {
if (scalar @$Line>2) {
push @MmpWarn, "$CurFile($LineNum) : Can't specify more than 2 Uids\n";
next LINE;
}
foreach (@$Line) {
$_=&Genutl_AnyToHex($_);
if (defined $_) {
push @{$CurResource{Uids}}, $_;
next;
}
push @MmpDie, "$CurFile($LineNum) : Uid doesn't fit expected number format\n";
next LINE;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Uids specified for Resource keyword UID\n";
next LINE;
}
if (/^DEPENDS$/o) {
# Note that DEPENDS lines are tolerated, but ignored - these are only relevant to build systems
# other than ABLD
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Unrecognised Resource Keyword \"$_\"\n";
}
if (/^WCHARENTRYPOINT$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
if ($TrgType=~/^STDEXE$/io) {
$WideCharMain=1;
}
else{
push @MmpWarn, "$CurFile($LineNum) : WCHARENTRYPOINT is supported only for Target Type STDEXE\n";
}
next LINE;
}
# ----------- handle body of START STRINGTABLE ... END -------------
if(%CurStringTable)
{
if (/^END$/o) {
my %stringtable = %CurStringTable;
push @StringTableStruct, \%stringtable;
undef %CurStringTable;
next LINE;
}
if (/^EXPORTPATH/o) {
if (scalar @$Line != 1) {
push @MmpDie, "$CurFile($LineNum) : Wrong number of arguments for EXPORTPATH\n";
}
if(defined $CurStringTable{ExportPath}) {
push @MmpDie, "$CurFile($LineNum) : Redefinition of EXPORTPATH\n";
}
else {
my $src=shift @$Line;
$CurStringTable{ExportPath} = $src;
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "STRINGTABLE EXPORTPATH", $CurStringTable{ExportPath}, $LineNum);
$CurStringTable{ExportPath} = &Path_Norm($CurStringTable{ExportPath});
$CurStringTable{ExportPath} =~ s/\\$//o; # ensure path doesn't end with a backslash (cl_generic.pm will add one)
$CurStringTable{ExportPath} = &Path_MakeEAbs($EPOCPath,$CurFile,$CurStringTable{ExportPath});
}
next LINE;
}
if (/^HEADERONLY$/o) {
if ($CurStringTable{Hdronly}) {
push @MmpWarn, "$CurFile($LineNum) : Stringtable HEADERONLY already specified\n";
next LINE;
}
$CurStringTable{Hdronly}="$CurFile($LineNum)";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Stringtable keyword HEADERONLY takes no arguments\n";
}
next LINE;
}
}
# ----------- handle top-level MMP file -------------------
if (/^START$/) {
unless ($_=uc shift @$Line) {
push @MmpWarn, "$CurFile($LineNum) : No Argument specified for START block\n";
next LINE;
}
foreach $MmpMacro (@{$$Plat_ref{MmpMacros}}) {
if ($_ eq $MmpMacro) {
$PlatTxtSwitch="$CurFile($LineNum)";
next LINE;
}
}
if ($_ eq 'BITMAP') {
unless ($CurBitMap{Trg}=shift @$Line) {
push @MmpWarn, "$CurFile($LineNum) : No Bitmap Target specified\n";
$CurBitMap{Trg}='NoTargetSpecified';
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for START BITMAP clause\n";
}
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "START BITMAP", $CurBitMap{Trg}, $LineNum);
$CurBitMap{Trg} = &Path_Norm($CurBitMap{Trg});
next LINE;
}
if ($_ eq 'RESOURCE') {
if (scalar @$Line != 1) {
push @MmpWarn, "$CurFile($LineNum) : Wrong number of arguments for START RESOURCE clause\n";
}
else {
my $src=shift @$Line;
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "START RESOURCE", $src, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$src = &Path_Norm($src);
$CurResource{Source}="$CurSrcPath$src";
}
next LINE;
}
if ($_ eq 'STRINGTABLE') {
if (scalar @$Line != 1) {
push @MmpWarn, "$CurFile($LineNum) : Wrong number of arguments for START STRINGTABLE clause\n";
}
else {
my $Candidate = shift @$Line;
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, "START STRINGTABLE", $Candidate, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$Candidate = &Path_Norm($Candidate);
$Candidate =~ s/^\\//; # remove leading \, if any
$CurStringTable{BaseTrg}=&Path_Split('Base',$Candidate);
my $path=&Path_Split('Path',$Candidate);
if($path){
$CurStringTable{STPath}=&Path_MakeAbs($CurSrcPath,&Path_Split('Path',$Candidate));
}
else {
$CurStringTable{STPath}=$CurSrcPath;
}
$CurStringTable{STFile}=&Path_Split('File',$Candidate);
}
next LINE;
}
$OtherPlatSwitch="$CurFile($LineNum)";
next LINE;
}
if (/^AIF$/o) {
my ($trg, $dir, $file, $clDepth, @bitmaps)=@$Line;
unless ($file) { # bitmaps aren't essential
push @MmpDie, "$CurFile($LineNum) : Not enough arguments for keyword AIF\n";
next LINE;
}
my %Data;
$Data{Trg} = $trg; # Defect: may include directory
$dir=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$Data{Source}=&Path_MakeAbs($CurFile, "$dir$file");
unless (-e "$Data{Source}") {
push @MmpWarn, "$CurFile($LineNum) : AIF source \"$Data{Source}\" not found\n";
}
if ($CheckAif{$Data{Trg}}) {
push @MmpDie, "$CurFile($LineNum) : Duplicate Aif \"$Data{Trg}\" at line $CheckAif{$Data{Trg}}\n";
next LINE;
}
$CheckAif{$Data{Trg}}="$CurFile($LineNum)";
push @AifStruct, \%Data;
next LINE unless (@bitmaps);
# handle bitmaps
my @ClDepths = split(/,/, $clDepth);
foreach (@ClDepths) {
$_ = lc $_; # bmconv can't handle upper-case 'C's
unless (/^c?\d\d?$/o) {
push @MmpDie, "$CurFile($LineNum) : AIF color depth \"$_\" - unexpected format\n";
}
}
@ClDepths = (@ClDepths) x @bitmaps; # make a sufficiently long list of color depths
foreach $file (@bitmaps) {
if ($file !~ /^\\/) {
$file = &Path_MakeAbs($CurFile, "$dir$file");
}
push @{$Data{BitMaps}}, { # sources must be kept in order
Src=>$file,
ClDepth=>shift @ClDepths # take next color depth from the list
};
unless (-e $file) {
push @MmpWarn, "$CurFile($LineNum) : AIF source \"$file\" not found\n";
}
}
next LINE;
}
if (/^ASSPABI$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$ASSPABISwitch=1;
next LINE;
}
if (/^ASSPEXPORTS$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$ASSPExports=1;
next LINE;
}
if (/^ASSPLIBRARY$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum);
$Candidate = &Path_Norm($Candidate);
unless ($emulator or &Genutl_ParseVersionedName(\$Candidate)) {
push @MmpWarn, "$CurFile($LineNum) : Bad version in ASSPLIBRARY\n";
}
if ($CheckASSPLib{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Library \"$Candidate\" at line $CheckASSPLib{$Candidate}\n";
next;
}
push @ASSPLibList, $Candidate;
$CheckASSPLib{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Libraries specified for keyword ASSPLIBRARY\n";
next LINE;
}
if (/^CAPABILITY$/o) {
if (defined($Capability)) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine CAPABILITY\n";
next LINE;
}
if (scalar @$Line == 0) {
push @MmpWarn, "$CurFile($LineNum) : Wrong number of arguments for CAPABILITY\n";
next LINE;
}
foreach my $capname (@$Line) {
my $invert = 0;
if ($capname =~ /^-(\w*)/) {
$invert = 0xffffffff;
$capname = $1;
}
my $capFlag = 0;
if (defined($CapabilityNames{uc $capname})) {
$capFlag = $CapabilityNames{uc $capname};
if (not $capFlag) {
push @MmpDiagnostic, "$CurFile($LineNum) : Use of old capability name, \"$capname\" ignored\n";
next;
}
if ("ALL" eq uc $capname and $invert) {
push @MmpWarn, "Capability '-ALL' not allowed";
next;
}
}
elsif ("NONE" eq uc $capname) {
if($invert) {
push @MmpWarn, "Capability '-NONE' not allowed";
next;
}
}
else {
push @MmpWarn, "$CurFile($LineNum) : Unknown capability \"$capname\" ignored\n";
next;
}
# append name to capability string
if (defined($Capability) and not $invert) { $Capability .= "+"; }
if($invert) { $Capability .= "-"; }
$Capability .= $capname;
# add capability mask to flags
$CapabilityFlags[0] = $CapabilityFlags[0] ^ $invert;
$CapabilityFlags[0] = $CapabilityFlags[0] | $capFlag;
$CapabilityFlags[0] = $CapabilityFlags[0] ^ $invert;
$CapabilityFlags[1] = 0;
next;
}
next LINE;
}
if (/^DEBUGLIBRARY$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum);
$Candidate = &Path_Norm($Candidate);
unless ($emulator or &Genutl_ParseVersionedName(\$Candidate)) {
push @MmpWarn, "$CurFile($LineNum) : Bad version in DEBUGLIBRARY\n";
}
if ($CheckLib{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Library \"$Candidate\" at line $CheckLib{$Candidate}\n";
next;
}
push @DebugLibList, $Candidate;
$CheckLib{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Libraries specified for keyword DEBUGLIBRARY\n";
next LINE;
}
if (/^DEFFILE$/o) {
if ($CheckDef) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine DEFFILE\n";
next LINE;
}
$CheckDef=1;
unless ($_=shift @$Line) {
push @MmpWarn, "$CurFile($LineNum) : No file specified for keyword DEFFILE\n";
next LINE;
}
$Def{CheckSource_MMPEntry} = $_;
$Def{CheckSource_LineNumber} = $LineNum;
$Def{CheckSource_MMPFile} = $CurFile;
$_ = &Path_Norm($_);
$Def{Base}=&Path_Split('Base',$_);
$Def{Ext}=&Path_Split('Ext',$_);
$Def{Path}=&Path_Split('Path',$_);
if ($Def{Path}) {
$Def{Path}=&Path_MakeEAbs($EPOCPath,$CurFile,$Def{Path});
}
if ($Def{Base} =~ /\{|\}/) {
push @MmpDie, "$CurFile($LineNum) : Bad DEFFILE name\n";
}
next LINE;
}
if (/^DOCUMENT$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$Candidate = &Path_Norm($Candidate);
if ($CheckDoc{"$CurSrcPath$Candidate"}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Document \"$CurSrcPath$Candidate\" at line ", $CheckDoc{"$CurSrcPath$Candidate"}, "\n";
next;
}
unless (-e "$CurSrcPath$Candidate") {
push @MmpWarn, "$CurFile($LineNum) : DOCUMENT \"$CurSrcPath$Candidate\" not found\n";
}
push @{$DocHash{$CurSrcPath}}, $Candidate;
$CheckDoc{"$CurSrcPath$Candidate"}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Files specified for keyword DOCUMENT\n";
next LINE;
}
if (/^EPOCALLOWDLLDATA$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$AllowDllData=1;
next LINE;
}
if (/^ALWAYS_BUILD_AS_ARM$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$BuildAsARM=1;
next LINE;
}
if (/^EPOCCALLDLLENTRYPOINTS$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$CallDllEntryPoints=1;
next LINE;
}
if (/^EPOCDATALINKADDRESS$/o) {
if (@$Line) {
my $temp=&main::Genutl_AnyToHex(shift @$Line);
if (defined $temp) {
$DataLinkAddress=$temp;
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : Data link address doesn't fit expected number format\n";
}
push @MmpWarn, "$CurFile($LineNum) : No data link address specified for keyword $_\n";
next LINE;
}
if (/^EPOCFIXEDPROCESS$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$FixedProcess=1;
next LINE;
}
if (/^EPOCHEAPSIZE$/o) {
if (@$Line) {
my $tempMin=&main::Genutl_AnyToHex(shift @$Line);
if (defined $tempMin) {
if (@$Line) {
my $tempMax=&main::Genutl_AnyToHex(shift @$Line);
if (defined $tempMax) {
$HeapSize{Min}=$tempMin;
$HeapSize{Max}=$tempMax;
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : maximum heap size doesn't fit expected number format\n";
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : No maximum heap size specified for keyword $_\n";
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : minimum heap size doesn't fit expected number format\n";
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No minimum heap size specified for keyword $_\n";
next LINE;
}
if (/^EPOCPROCESSPRIORITY$/o) {
if ($ProcessPriority) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine EPOCPROCESSPRIORITY\n";
next LINE;
}
if ($ProcessPriority=shift @$Line) {
if (defined($ProcessPriorityNames{uc $ProcessPriority})) {
$ProcessPriority = $ProcessPriorityNames{uc $ProcessPriority}; # canonical form
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : ProcessPriority \"$ProcessPriority\" not supported\n";
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Priority specified for keyword EPOCPROCESSPRIORITY\n";
next LINE;
}
if (/^EPOCSTACKSIZE$/o) {
if (@$Line) {
my $temp=&main::Genutl_AnyToHex(shift @$Line);
if (defined $temp) {
$StackSize=$temp;
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : Stack size doesn't fit expected number format\n";
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No stack size specified for keyword STACKSIZE\n";
next LINE;
}
if (/^COMPRESSTARGET$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$CompressTarget=COMPRESS;
$CompressTargetMethod=NOCOMPRESSIONMETHOD; # means 'use default'
next LINE;
}
if (/^NOCOMPRESSTARGET$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$CompressTarget=NOCOMPRESS;
$CompressTargetMethod=NOCOMPRESSIONMETHOD;
next LINE;
}
if (/^INFLATECOMPRESSTARGET$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$CompressTarget=COMPRESS;
$CompressTargetMethod=INFLATECOMPRESSIONMETHOD;
next LINE;
}
if (/^BYTEPAIRCOMPRESSTARGET$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$CompressTarget=COMPRESS;
$CompressTargetMethod=BYTEPAIRCOMPRESSIONMETHOD;
next LINE;
}
if (/^EXPORTUNFROZEN$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$ExportUnfrozen=1;
next LINE;
}
if (/^FIRSTLIB$/o) {
if ($FirstLib) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine FIRSTLIB\n";
next LINE;
}
if ($FirstLib=shift @$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $FirstLib, $LineNum);
$FirstLib = &Path_Norm($FirstLib);
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Nothing specified for keyword FIRSTLIB\n";
next LINE;
}
if (/^LANG$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
if ($CheckLang{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Language \"$Candidate\" at line $CheckLang{$Candidate}\n";
next;
}
push @LangList, $Candidate;
$CheckLang{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Languages specified for keyword LANG\n";
next LINE;
}
if (/^LIBRARY$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum);
$Candidate = &Path_Norm($Candidate);
unless ($emulator or &Genutl_ParseVersionedName(\$Candidate)) {
push @MmpWarn, "$CurFile($LineNum) : Bad version in LIBRARY\n";
}
if ($CheckLib{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Library \"$Candidate\" at line $CheckLib{$Candidate}\n";
next;
}
push @LibList, $Candidate;
push @DebugLibList, $Candidate; # appears in both
$CheckLib{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Libraries specified for keyword LIBRARY\n";
next LINE;
}
if (/^LINKAS$/o) {
if ($LinkAs) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine LINKAS\n";
next LINE;
}
if ($LinkAs=shift @$Line) {
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No name specified for keyword LINKAS\n";
next LINE;
}
if (/^EXPORTLIBRARY$/o) {
if ($NoExportLibrary) {
push @MmpDie, "$CurFile($LineNum) : Can't specify both EXPORTLIBRARY and NOEXPORTLIBRARY\n";
next LINE;
}
if ($ExportLibrary) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine EXPORTLIBRARY\n";
next LINE;
}
if ($ExportLibrary=shift @$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $ExportLibrary, $LineNum);
$ExportLibrary = &Path_Norm($ExportLibrary);
$ExportLibrary=&Path_Split('Base',$ExportLibrary);
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No name specified for keyword EXPORTLIBRARY\n";
next LINE;
}
if (/^NOEXPORTLIBRARY$/o) {
if ($ExportLibrary) {
push @MmpDie, "$CurFile($LineNum) : Can't specify both EXPORTLIBRARY and NOEXPORTLIBRARY\n";
next LINE;
}
$NoExportLibrary = 1;
next LINE;
}
if (/^NEWLIB$/o) {
if ($NewLib) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine NEWLIB\n";
next LINE;
}
if ($NewLib = shift @$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $NewLib, $LineNum);
$NewLib = &Path_Norm($NewLib);
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No library specified for keyword NEWLIB\n";
next LINE;
}
if (/^MACRO$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
if ($CheckMacro{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Macro \"$Candidate\" at line $CheckMacro{$Candidate}\n";
next;
}
push @Macros, $Candidate;
$CheckMacro{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
next LINE;
}
if (/^NOSTRICTDEF$/o) {
if ($NoStrictDef) {
push @MmpWarn, "$CurFile($LineNum) : NOSTRICTDEF already set\n";
next LINE;
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword NOSTRICTDEF takes no arguments\n";
}
$NoStrictDef=1;
next LINE;
}
if (/^RAMTARGET$/o) {
if ($CheckRamTargets) {
push @MmpWarn, "$CurFile($LineNum) : RAM targets already specified at line $CheckRamTargets\n";
next LINE;
}
$CheckRamTargets="$CurFile($LineNum)";
unless (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : No targets specified for keyword RAMTARGET\n";
next LINE;
}
if ($$Line[0] eq '+') {
my %Data=();
push @RamTargets, \%Data; # include default
shift @$Line;
}
my $Elem;
foreach $Elem (@$Line) {
my %Data=();
$Data{File}=&Path_Split('File',$Elem);
$Data{Path}=&Path_Split('Path',$Elem);
push @RamTargets, \%Data;
}
next LINE;
}
if (/^RESOURCE$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$Candidate = &Path_Norm($Candidate);
if ($CheckResrc{$Candidate}) {
push @MmpDie, "$CurFile($LineNum) : Duplicate Resource $Candidate at line $CheckResrc{$Candidate}\n";
next;
}
$CheckResrc{$Candidate}="$CurFile($LineNum)";
my $source="$CurSrcPath$Candidate";
unless (-e $source) {
push @MmpWarn, "$CurFile($LineNum) : RESOURCE source \"$source\" not found\n";
}
$CurResource{BaseTrg}=&Path_Split('Base',$Candidate);
$CurResource{Source}=$source;
$CurResource{Hdr}="$CurFile($LineNum)";
# $CurResource{TrgPath} will be filled in at the end;
my %Resource=%CurResource;
undef %CurResource;
push @ResourceStruct, \%Resource;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Resources specified for keyword RESOURCE\n";
next LINE;
}
if (/^ROMTARGET$/o) {
if ($CheckRomTargets) {
push @MmpWarn, "$CurFile($LineNum) : ROM targets already specified at line $CheckRomTargets\n";
next LINE;
}
$CheckRomTargets="$CurFile($LineNum)";
unless (@$Line) {
@RomTargets=();
next LINE;
}
if ($$Line[0] eq '+') {
shift @$Line;
}
else {
@RomTargets=(); # remove default
}
my $Elem;
foreach $Elem (@$Line) {
my %Data=();
$Data{File}=&Path_Split('File',$Elem);
$Data{Path}=&Path_Split('Path',$Elem);
push @RomTargets, \%Data;
}
next LINE;
}
if (/^SMPSAFE$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$SmpSafe = 1;
next LINE;
}
if (/^SOURCE$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$Candidate = &Path_Norm($Candidate);
$Candidate =~ s/^\\//; # remove leading \, if any
$CurSource{BaseTrg}=&Path_Split('Base',$Candidate);
my $path=&Path_Split('Path',$Candidate);
if($path){
$CurSource{SrcPath}=&Path_MakeAbs($CurSrcPath,&Path_Split('Path',$Candidate));
}
else {
$CurSource{SrcPath}=$CurSrcPath;
}
$CurSource{CurFile}=&Path_Split('File',$Candidate);
my %Source=%CurSource;
undef %CurSource;
push @SourceStruct, \%Source;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Sources specified for keyword SOURCE\n";
next LINE;
}
if (/^SOURCEPATH$/o) {
if ($CurSrcPath=shift @$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $CurSrcPath, $LineNum, $CheckSource_PhysicalCheck);
$CurSrcPath = &Path_Norm($CurSrcPath);
$CurSrcPath=~s-^(.*[^\\])$-$1\\-o; # in case no terminating backslash
$CurSrcPath=&Path_MakeEAbs($EPOCPath,$CurFile,$CurSrcPath);
if (-d &Path_Chop($CurSrcPath)) {
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : SOURCEPATH \"$CurSrcPath\" not found\n";
next LINE;
}
push @MmpDie, "$CurFile($LineNum) : No Source Path specified for keyword SOURCEPATH\n";
next LINE;
}
if (/^STATICLIBRARY$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum);
$Candidate = &Path_Norm($Candidate);
if ($CheckStatLib{$Candidate}) {
push @MmpWarn, "$CurFile($LineNum) : Duplicate Library \"$Candidate\" at line $CheckStatLib{$Candidate}\n";
next;
}
push @StatLibList, $Candidate;
$CheckStatLib{$Candidate}="$CurFile($LineNum)";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Libraries specified for keyword STATICLIBRARY\n";
next LINE;
}
if (/^STDCPP$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$StdCpp=1;
next LINE;
}
if (/^NOSTDCPP$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$NoStdCpp=1;
next LINE;
}
if (/^STRICTDEPEND$/o) {
if ($MmpFlag{StrictDepend}) {
push @MmpWarn, "$CurFile($LineNum) : STRICTDEPEND already set\n";
next LINE;
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword STRICTDEPEND takes no arguments\n";
}
$MmpFlag{StrictDepend}=1;
next LINE;
}
if (/^SYSTEMINCLUDE$/o){
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck);
$Candidate = &Path_Norm($Candidate);
$Candidate=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$Candidate=&Path_MakeEAbs($EPOCPath,$CurFile,$Candidate);
if ($CheckSysInc{$Candidate}) {
next;
}
push @SysIncPaths,$Candidate;
$CheckSysInc{$Candidate}="$CurFile($LineNum)";
if (-d &Path_Chop($Candidate)) {
next;
}
push @MmpWarn, "$CurFile($LineNum) : SYSTEMINCLUDE path \"$Candidate\" not found\n";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Paths specified for keyword SYSTEMINCLUDE\n";
next LINE;
}
if (/^SYSTEMRESOURCE$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck, $CurSrcPath);
$Candidate = &Path_Norm($Candidate);
if ($CheckSysResrc{$Candidate}) {
push @MmpDie, "$CurFile($LineNum) : Duplicate Resource \"$Candidate\" at line $CheckSysResrc{$Candidate}\n";
next;
}
$CheckSysResrc{$Candidate}="$CurFile($LineNum)";
my $source="$CurSrcPath$Candidate";
unless (-e $source) {
push @MmpWarn, "$CurFile($LineNum) : SYSTEMRESOURCE source \"$source\" not found\n";
}
$CurResource{BaseTrg}=&Path_Split('Base',$Candidate);
$CurResource{Source}=$source;
$CurResource{Hdr}="$CurFile($LineNum)";
$CurResource{TrgPath}="z\\system\\data\\"; # needs to match e32env.pm
my %Resource=%CurResource;
undef %CurResource;
push @ResourceStruct, \%Resource;
}
if (&main::EPOCSecurePlatform()) {
push @MmpMigrationNote, "Obsolete SYSTEMRESOURCE keyword specified in \"$MMPFILE\"";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Resources specified for keyword SYSTEMRESOURCE\n";
next LINE;
}
if (/^TARGET$/o) {
if ($Trg) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine TARGET\n";
next LINE;
}
if ($Trg=shift @$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Trg, $LineNum);
$Trg = &Path_Norm($Trg);
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Target specified for keyword TARGET\n";
next LINE;
}
if (/^TARGETPATH$/o) {
if ($TrgPath) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine TARGETPATH\n";
next LINE;
}
unless ($TrgPath=shift @$Line) {
push @MmpWarn, "$CurFile($LineNum) : No Path specified for keyword TARGETPATH\n";
next LINE;
}
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $TrgPath, $LineNum);
$TrgPath = &Path_Norm($TrgPath);
$TrgPath=~s-^\\(.*)$-$1-o;
$TrgPath=~s-^(.*[^\\])$-$1\\-o;
$TrgPath="z\\$TrgPath";
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for keyword TARGETPATH\n";
}
next LINE;
}
if (/^TARGETTYPE$/o) {
if ($TrgType) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine TARGETTYPE\n";
next LINE;
}
unless ($TrgType=shift @$Line) {
push @MmpWarn, "$CurFile($LineNum) : No Type specified for keyword TARGETTYPE\n";
next LINE;
}
eval { &Trg_GetL($TrgType, \%TrgType); };
if ($@) {
push @MmpDie, "$CurFile($LineNum) : $@";
}
next LINE;
}
if (/^UID$/o) {
if (@$Line) {
foreach (@$Line) {
if ($#UidList>=1) {
push @MmpWarn, "$CurFile($LineNum) : Can't specify more than 2 Uids\n";
next LINE;
}
$_=&Genutl_AnyToHex($_);
if (defined $_) {
push @UidList, $_;
next;
}
push @MmpDie, "$CurFile($LineNum) : Uid doesn't fit expected number format\n";
next LINE;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Uids specified for keyword UID\n";
next LINE;
}
if (/^SECUREID$/o) {
if ($SecureId) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine SECUREID\n";
next LINE;
}
if (@$Line) {
$SecureId = &Genutl_AnyToHex(shift @$Line);
if (!defined $SecureId) {
push @MmpDie, "$CurFile($LineNum) : SECUREID doesn't fit expected number format\n";
next LINE;
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for keyword SECUREID\n";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Missing argument for keyword SECUREID\n";
next LINE;
}
if (/^VENDORID$/o) {
if (defined($VendorId)) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine VENDORID\n";
next LINE;
}
if (@$Line) {
$VendorId = &Genutl_AnyToHex(shift @$Line);
if (!defined $VendorId) {
push @MmpDie, "$CurFile($LineNum) : VENDORID doesn't fit expected number format\n";
next LINE;
}
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Too many arguments for keyword VENDORID\n";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Missing argument for keyword VENDORID\n";
next LINE;
}
if (/^USERINCLUDE$/o) {
if (@$Line) {
my $Candidate;
foreach $Candidate (@$Line) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $CurFile, $mainElement, $Candidate, $LineNum, $CheckSource_PhysicalCheck);
$Candidate = &Path_Norm($Candidate);
$Candidate=~s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$Candidate=&Path_MakeEAbs($EPOCPath,$CurFile,$Candidate);
if ($CheckUserInc{$Candidate}) {
next;
}
push @UserIncPaths,$Candidate;
$CheckUserInc{$Candidate}="$CurFile($LineNum)";
if (-d &Path_Chop($Candidate)) {
next;
}
push @MmpWarn, "$CurFile($LineNum) : USERINCLUDE path \"$Candidate\" not found\n";
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : No Paths specified for keyword USERINCLUDE\n";
next LINE;
}
if (/^SRCDBG$/o) {
if (@$Line) {
push @MmpWarn, "$CurFile($LineNum) : Keyword $_ takes no arguments\n";
}
$SrcDbg=1;
next LINE;
}
if (/^VERSION$/o) {
if (%Version) {
push @MmpDie, "$CurFile($LineNum) : Attempt to redefine VERSION\n";
next LINE;
}
unless (@$Line) {
push @MmpDie, "$CurFile($LineNum) : Missing argument to VERSION\n";
next LINE;
}
%Version = &Genutl_StringToVersion(shift @$Line);
if (!%Version) {
push @MmpDie, "$CurFile($LineNum) : Bad VERSION number\n";
next LINE;
}
if (@$Line) {
if ((lc $$Line[0]) eq 'explicit') {
$Version{explicit} = 1;
shift @$Line;
}
if (scalar(@$Line)) {
push @MmpDie, "$CurFile($LineNum) : Garbage after VERSION number\n";
}
}
next LINE;
}
if (/^OPTION$/oi ) {
if (@$Line >= 2) {
my $compilerkey= uc shift @$Line;
if (!defined($Compiler{$compilerkey})) {
# first use of "OPTION xxx"
$Compiler{$compilerkey}=shift @$Line;
}
# concatenate extra stuff
while (@$Line) {
$Compiler{$compilerkey}.=" ".shift @$Line;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Keyword OPTION requires at least two arguments\n";
next LINE;
}
if (/^LINKEROPTION$/oi ) {
if (@$Line >= 2) {
# first parameter is the compiler
my $compilerkey= uc shift @$Line;
if (!defined($Compiler{$compilerkey})) {
# first use of "LINKEROPTION xxx"
$LinkerOptions{$compilerkey}=shift @$Line;
}
# concatenate extra stuff
while (@$Line) {
$LinkerOptions{$compilerkey}.=" ".shift @$Line;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Keyword LINKEROPTION requires at least two arguments\n";
next LINE;
}
if (/^OPTION_Replace$/oi ) {
if (@$Line >= 2) {
my $compilerkey= uc shift @$Line;
my $repOptions= shift @$Line;
while (@$Line)
{
$repOptions.= " ".shift @$Line;
}
$repOptions =~ s/=\s*/=/g;
push @{$Replace{$compilerkey}},$repOptions;
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Keyword OPTION_Replace requires at least two arguments\n";
next LINE;
}
if (/^ARMFPU$/oi) {
if ($ARMFPU) {
push @MmpWarn, "$CurFile($LineNum) : Attempt to redefine ARMFPU\n";
next LINE;
}
if ($ARMFPU=shift @$Line) {
if (($ARMFPU !~ /^SOFTVFP$/oi) && ($ARMFPU !~ /^VFPV2$/oi)) {
push @MmpWarn, "$CurFile($LineNum) : ARMFPU can only specify SOFTVFP or VFPV2 as an argument\n";
undef $ARMFPU;
}
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : ARMFPU must specify either SOFTVFP or VFPV2 as an argument\n";
next LINE;
}
if( /^PAGED$/o) {
if ($CodePagingTargetMode == PAGED or $DataPagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($CodePagingTargetMode == UNPAGED or $DataPagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$CodePagingTargetMode = PAGED;
$DataPagingTargetMode = PAGED;
next LINE;
}
if( /^UNPAGED$/o) {
if ($CodePagingTargetMode == UNPAGED or $DataPagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($CodePagingTargetMode == PAGED or $DataPagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$CodePagingTargetMode = UNPAGED;
$DataPagingTargetMode = UNPAGED;
next LINE;
}
if( /^PAGEDCODE$/o) {
if ($CodePagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($CodePagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$CodePagingTargetMode = PAGED;
next LINE;
}
if( /^UNPAGEDCODE$/o) {
if ($CodePagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($CodePagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$CodePagingTargetMode = UNPAGED;
next LINE;
}
if( /^PAGEDDATA$/o) {
if ($DataPagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($DataPagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$DataPagingTargetMode = PAGED;
next LINE;
}
if( /^UNPAGEDDATA$/o) {
if ($DataPagingTargetMode == UNPAGED) {
push @MmpWarn, "$CurFile($LineNum) : duplicate paging setting\n";
}
if ($DataPagingTargetMode == PAGED) {
push @MmpWarn, "$CurFile($LineNum) : conflict paging setting\n";
}
$DataPagingTargetMode = UNPAGED;
next LINE;
}
if( /^DEBUGGABLE_UDEBONLY$/o) {
$IsDebuggable = DEBUGGABLE_UDEBONLY;
next LINE;
}
if( /^DEBUGGABLE$/o) {
if ($IsDebuggable != DEBUGGABLE_UDEBONLY)
{
$IsDebuggable = DEBUGGABLE;
}
next LINE;
}
if( /^FEATUREVARIANT$/o) {
push @MmpDie, "$CurFile($LineNum) : FEATUREVARIANT specified multiple times" if ($FeatureVariant);
$FeatureVariant = 1;
next LINE;
}
push @MmpWarn, "$CurFile($LineNum) : Unrecognised Keyword \"$_\"\n";
}
undef $Line;
undef $MmpMacro;
# test the mmp contents
#----------------------
if ($PlatTxtSwitch || $OtherPlatSwitch) {
push @MmpDie, $PlatTxtSwitch ? $PlatTxtSwitch : $OtherPlatSwitch, ": Unterminated START ... END block\n";
}
undef $PlatTxtSwitch;
undef $OtherPlatSwitch;
# Check the consistency of the mmp file contents
unless ($Trg) {
unless($TrgType=~/^NONE$/io){
push @MmpDie, "ERROR: No Target specified\n";
}
}
unless ($TrgType) {
push @MmpDie, "ERROR: No TargetType specified\n";
}
if( $StdCpp && $NoStdCpp ) {
push @MmpWarn, "WARNING: Keyword statement STDCPP not permitted with keyword NOSTDCPP.\n";
push @MmpWarn, "WARNING: Keyword statements STDCPP and NOSTDCPP ignored.\n";
$StdCpp = 0;
$NoStdCpp = 0;
}
if (($TrgType =~ /^LIB$/io) && (scalar(@DebugLibList) || scalar(@LibList) || scalar(@StatLibList))) {
push @MmpWarn, "WARNING: Library statements (DEBUGLIBRARY, LIBRARY or STATICLIBRARY) not permitted with TARGETTYPE LIB.";
push @MmpWarn, "WARNING: Library statements (DEBUGLIBRARY, LIBRARY or STATICLIBRARY) ignored.\n";
undef @DebugLibList;
undef @LibList;
undef @StatLibList;
}
if ($TrgType =~ /^LIB$/io && $NewLib) {
push @MmpWarn, "WARNING: Library statement NEWLIB not permitted with TARGETTYPE LIB.";
push @MmpWarn, "WARNING: Library statement NEWLIB ignored.\n";
undef @DebugLibList;
undef @LibList;
undef @StatLibList;
}
if ($TrgType =~ /^STD(EXE|DLL)$/io && $NewLib) {
push @MmpWarn, "WARNING: Library statement NEWLIB not permitted with TARGETTYPE STD*.";
push @MmpWarn, "WARNING: Library statement NEWLIB ignored.\n";
undef @DebugLibList;
undef @LibList;
undef @StatLibList;
}
if (($TrgType=~/^IMPLIB$/io) || ($TrgType=~/^NONE$/io)) {
push @MmpDie, "ERROR: SOURCE not permitted with TARGETTYPE $TrgType\n" if (@SourceStruct);
} elsif (!@SourceStruct) {
push @MmpDie, "ERROR: No Sources specified\n";
}
if ($TrgType{NeedUID3} && $#UidList<1) {
push @MmpWarn, "WARNING: No Uid3 specified in \"$MMPFILE\" for TargetType \"$TrgType\"\n";
}
if ($Trg && $Trg=~/\{|\}/) {
push @MmpDie, "ERROR: Bad TARGET name specified\n";
}
if ($ExportLibrary and $ExportLibrary=~/\{|\}/) {
push @MmpDie, "ERROR: Bad EXPORTLIBRARY name specified\n";
}
if ($LinkAs and $LinkAs=~/\{|\}/) {
push @MmpDie, "ERROR: Bad LINKAS name specified\n";
}
# Make sure a valid compression method has been chosen if target is going to be paged
if ($CodePagingTargetMode == PAGED && $CompressTarget == COMPRESS) {
if ($CompressTargetMethod == INFLATECOMPRESSIONMETHOD) {
push @MmpWarn, "Incompatible keywords! The INFLATECOMPRESSTARGET is not allowed with PAGED!\n";
push @MmpWarn, "Changing compression method to BYTEPAIRCOMPRESSTARGET\n";
}
$CompressTargetMethod = BYTEPAIRCOMPRESSIONMETHOD;
}
# Ensure 2nd UID is not deprecated
if (&main::EPOCSecurePlatform() && $TrgType{Basic} eq "DLL")
{
$deprecatedUIDs{"0x100039ce"} = "Unmigrated dll style application detected from use of UID 0x100039ce";
}
# Do not need UIDs for a resource only (i.e. TARGETTYPE is "none") mmp file
if ((!$TrgType=~/^NONE$/io) && &main::EPOCSecurePlatform() && defined($deprecatedUIDs{$UidList[0]}))
{
push @MmpMigrationNote, "$deprecatedUIDs{$UidList[0]}\n";
}
# PUT IN SOME DEFAULTS
if ($TrgPath eq '') {
# set up default path from $TrgType
$TrgPath = $TrgType{Path};
}
my $ResourceTrgPath = $TrgType{ResourcePath};
if ($ResourceTrgPath eq '') {
$ResourceTrgPath = $TrgPath; # default to TrgPath, as before
}
unless (%Version) {
if ($$Plat_ref{DefFile} =~ /^\s*EABI\s*/i ) {
$Version{major} = 10; # Start major versions at 10 for EABI to allow coexistence with GCC98r2 ABI
} else {
$Version{major} = 1;
}
$Version{minor} = 0;
}
# check for languages
@LangList=('SC') unless @LangList;
if (&main::EPOCSecurePlatform() && !defined($Capability) &&
(($TrgType{Basic} eq "DLL") || (uc($TrgType) eq "EXEXP")))
{
push @MmpMigrationNote, "No Capabilities set in \"$MMPFILE\" for TargetType: $TrgType\n";
}
# Supply default capability mask if not set explicitly, and convert to hex string
$Capability = "none" unless (defined($Capability));
$CapabilityFlags[0] = 0 unless (defined($CapabilityFlags[0]));
$CapabilityFlags[1] = 0 unless (defined($CapabilityFlags[1]));
$CapabilityFlags[0] = sprintf("0x%08x", $CapabilityFlags[0]);
$CapabilityFlags[1] = sprintf("0x%08x", $CapabilityFlags[1]);
# ensure all bitmaps have targetpaths and check for duplicate bitmaps
my %BitMapCheck;
my $BitMapRef;
foreach $BitMapRef (@BitMapStruct) {
unless ($$BitMapRef{TrgPath}) {
$$BitMapRef{TrgPath}=$ResourceTrgPath;
}
if ($BitMapCheck{"$$BitMapRef{TrgPath}$$BitMapRef{Trg}"}) {
push @MmpDie, "ERROR: Duplicate bitmap target \"$$BitMapRef{TrgPath}$$BitMapRef{Trg}\"\n";
next;
}
$BitMapCheck{"$$BitMapRef{TrgPath}$$BitMapRef{Trg}"}=1;
}
# ensure all resources have targetpaths, expand language list and check for duplicates
my %ResourceCheck;
my $ResourceRef;
my @PerLanguageResourceStruct;
foreach $ResourceRef (@ResourceStruct) {
unless ($$ResourceRef{BaseTrg}) {
$$ResourceRef{BaseTrg}=&Path_Split('Base',$$ResourceRef{Source});
}
unless ($$ResourceRef{TrgPath}) {
$$ResourceRef{TrgPath}=$ResourceTrgPath;
}
unless ($$ResourceRef{Lang}) {
@{$$ResourceRef{Lang}}=@LangList;
}
# generate one instance per language.
my @list = @{$$ResourceRef{Lang}};
my $base = "$$ResourceRef{TrgPath}$$ResourceRef{BaseTrg}";
foreach my $lang (@list) {
my %newResourceRef = %{$ResourceRef};
$newResourceRef{Lang} = $lang;
$newResourceRef{Trg} = $base.lc("\.R$lang");
push @PerLanguageResourceStruct, \%newResourceRef;
}
}
@ResourceStruct = @PerLanguageResourceStruct;
undef @PerLanguageResourceStruct;
foreach $ResourceRef (@ResourceStruct) {
if ($ResourceCheck{"$$ResourceRef{TrgPath}$$ResourceRef{Trg}"}) {
push @MmpDie, "ERROR: Duplicate Resource target \"$$ResourceRef{TrgPath}$$ResourceRef{Trg}\"\n";
next;
}
$ResourceCheck{"$$ResourceRef{TrgPath}$$ResourceRef{Trg}"}=1;
}
my $Plat=&main::Plat;
if (@MmpDie || @MmpWarn || @MmpDiagnostic || @MmpMigrationNote) {
warn "\nMMPFILE \"$MMPFILE\"\n";
if (@MmpDiagnostic) {
warn
"DIAGNOSTIC MESSAGE(S)\n",
@MmpDiagnostic,
"\n"
;
}
foreach my $printedWarning (@MmpWarn)
{
print "WARNING: $printedWarning\n";
}
foreach my $printedError (@MmpDie)
{
print "FATAL ERROR: $printedError\n";
}
foreach my $printedMigrationNote (@MmpMigrationNote)
{
print "MIGRATION_NOTE: $printedMigrationNote\n";
}
if (@MmpDie)
{
die;
}
}
# COMPLETE THE UID LIST
while ($#UidList<1) {
push @UidList, '0x00000000';
}
# check the second UID, or set it
if ($TrgType{UID2}) {
if ($UidList[0]=~/^0x00000000$/o) {
# put in second uid for known targetypes without them
$UidList[0]=$TrgType{UID2};
}
elsif ($UidList[0] ne $TrgType{UID2}) {
# text comparison is OK here because UIDs have both been through AnyToHex function
if ($UidList[0] ne '0x01111111') {
# issue warning (but not if UID == 0x01111111 (to allow test code to deliberately set incorrect UID)
warn(
"WARNING: Second Uid is $UidList[0], but\n",
" expected value for Target Type $TrgType is $TrgType{UID2}\n"
);
}
}
}
# Put in the first UID in the list
if ($TrgType{Basic}=~/^DLL$/o) {
unshift @UidList, '0x10000079';
}
elsif ($TrgType{Basic}=~/^(EXE)$/o) {
unshift @UidList, '0x1000007a';
}
elsif ($TrgType{Basic}=~/^(EXEDLL)$/o) {
# EXE on EPOC32, DLL on Emulator
# NOTE: On EKA1 EXEDLL used EXE UID1 on emulator
# On EKA2 this is unacceptable
if (!$emulator) {
unshift @UidList, '0x1000007a';
} else {
unshift @UidList, '0x10000079';
}
}
else {
unshift @UidList, '0x00000000';
}
# If no SID specified use UID3
$SecureId = $UidList[2] unless(defined $SecureId);
# SORT OUT TARGET TYPE DATA STRUCTURE
# set the target path
if ($TrgPath) {
$TrgType{Path}=$TrgPath;
}
# put in the $Linkas default
if (!$LinkAs and $TrgType=~/^IMPLIB$/io) {
$LinkAs = $Trg;
$LinkAs =~ s/\.lib$/\.dll/i;
} else {
$LinkAs = $Trg unless $LinkAs;
}
$LinkAsBase = $LinkAs;
unless ($emulator) {
$LinkAs = &DecorateWithVersion($LinkAs, %Version);
}
# If explicit version add to target
if ($Version{explicit} && !$emulator) {
$Trg = &DecorateWithVersion($Trg, %Version);
}
# Reconcile any EXEDLL targettypes - must be done after first UIDs put in the list
# and after the $LinkAs keyword has been defined/defaulted
if ($TrgType{Basic} eq 'EXEDLL') {
$TrgType{Basic} = $emulator ? 'DLL' : 'EXE';
$Trg=&Path_Split('Base',$Trg).'.EXE';
$LinkAsBase=&Path_Split('Base',$LinkAsBase).'.EXE';
$LinkAs=&Path_Split('Base',$LinkAs).'.EXE';
}
# put in the $ExportLibrary default
$ExportLibrary=&Path_Split('Base',$Trg) unless $ExportLibrary;
unless ($emulator) {
$ExportLibrary = &DecorateWithVersion($ExportLibrary, %Version);
}
# Get the EPOC entrypoint static library
unless ($FirstLib) {
unless ($TrgType{FirstLib}) {
$FirstLib="E$TrgType{Basic}.LIB";
}
else {
$FirstLib=$TrgType{FirstLib};
}
}
# WORK OUT THE ASSP IMPLICATIONS
# Nullify ASSP-specific API things for WINS/WINC since the API should always be
# the same for WINC as for WINS,
if ($emulator) {
$ASSPABISwitch=0;
$ASSPExports=0;
unshift @LibList, @ASSPLibList;
unshift @DebugLibList, @ASSPLibList; # keep DebugLibList in sync with LibList
@ASSPLibList=();
}
else {
# Force ASSPABISwitch for known kernel components or if ASSPEXPORTS or ASSPLIBRARY specified in .MMP file
if ($TrgType{Kernel} or $ASSPExports or @ASSPLibList) {
$ASSPABISwitch=1;
}
}
# Switch the ABI if necessary
unless ($ASSPABISwitch) {
# apply the standard ABI
$ABI=$$Plat_ref{ABI};
}
else {
# kernel-specific stuff
# check that the platform is not generic
if ($$Plat_ref{Generic}) {
die "ERROR: Can't apply ASSPABI, ASSPEXPORTS or ASSPLIBRARY for generic platform \"$$Plat_ref{Name}\n";
}
# apply the ASSP-specific ABI
$ABI=$$Plat_ref{ASSPABI};
}
# COMPLETE THE .DEF FILE STRUCTURE
# apply the default .DEF filename, and
# check as far as possible that the project is frozen
if (($TrgType{NeedDeffile} or $CheckDef)) {
unless ($Def{Path} and $Def{Path} !~ /\\\~\\$/) {
my $augment;
if ($ASSPExports) {
if ($$Plat_ref{DefFile} =~ /^\s*EABI\s*/i ) {
$augment = $$Plat_ref{ASSP};
} else {
$augment = "B$$Plat_ref{ASSP}";
}
} else {
if ($$Plat_ref{DefFile} =~ /^\s*EABI\s*/i ) {
$augment = lc($$Plat_ref{DefFile});
} else {
$augment = lc("B$$Plat_ref{DefFile}");
}
}
if ($Def{Path} =~ /\\\~\\$/) {
$Def{Path} =~ s/\\\~\\$/\\$augment\\/;
} else {
$Def{Path}=&Path_Strip(&Path_Split('Path',$MMPFILE)."..\\$augment\\");
}
}
unless ($Def{Base}) {
$Def{Base} = &Path_Split('Base',$LinkAsBase);
}
unless ($Def{Ext}) {
$Def{Ext}='.def';
}
# now that we've dumped narrow, treat the 'u' basename suffix as part of the frozen
# .DEF file basename. Once we've dumped the suffix we won't have to store the extension
# separately either
if (!$emulator && $Version{explicit}) {
$Def{Base} .= &Genutl_VersionToFileAugment(%Version);
} elsif (!$NoStrictDef) {
$Def{Base}.='u';
}
if ($Def{CheckSource_MMPEntry})
{
my $type = "DEFFILE";
$type .= " (NOSTRICTDEF)" if ($NoStrictDef);
# for GCCXML and X86GCC, ignore check source errors for missing .def file
my $checkdef = (($IgnoreMissingDef) && ($Def{Path} =~ /[\\\/]bmarm[\\\/]/ || $$Plat_ref{Name} eq "X86GCC" || $$Plat_ref{Name} eq "X86GMP")) ? 0 : 1;
if( $checkdef ) {
CheckSource_MetaData(%CheckSourceMMPMetaData, $Def{CheckSource_MMPFile}, $type, $Def{CheckSource_MMPEntry}, $Def{CheckSource_LineNumber}, $CheckSource_PhysicalCheck, $Def{Path});
}
}
# check deffile exists,
unless (-e "$Def{Path}$Def{Base}$Def{Ext}") {
if($IgnoreMissingDef == 0) {
warn "WARNING: Frozen .def file $Def{Path}$Def{Base}$Def{Ext} not found - project not frozen\n";
}
}
}
}
sub Mmp_ABI () {
$ABI;
}
sub Mmp_AifStruct () {
\@AifStruct;
}
sub Mmp_AllowDllData () {
$AllowDllData;
}
sub Mmp_CompressTarget () {
$CompressTarget;
}
sub Mmp_CompressTargetMode () {
$CompressTargetMethod;
}
sub Mmp_ASSPExports () {
$ASSPExports;
}
sub Mmp_ASSPLibList () {
@ASSPLibList;
}
sub Mmp_BitMapStruct () {
\@BitMapStruct;
}
sub Mmp_BuildAsARM () {
$BuildAsARM;
}
sub Mmp_CallDllEntryPoints () {
$CallDllEntryPoints;
}
sub Mmp_Capability () {
$Capability;
}
sub Mmp_CapabilityFlags () {
@CapabilityFlags;
}
sub Mmp_DataLinkAddress () {
$DataLinkAddress;
}
sub Mmp_DebugLibList () {
\@DebugLibList;
}
sub Mmp_Def () {
\%Def;
}
sub Mmp_DocHash () {
\%DocHash;
}
sub Mmp_ExportUnfrozen () {
$ExportUnfrozen;
}
sub Mmp_FirstLib () {
$FirstLib;
}
sub Mmp_FixedProcess () {
$FixedProcess;
}
sub Mmp_HeapSize () {
\%HeapSize;
}
sub Mmp_LibList () {
\@LibList;
}
sub Mmp_LinkAs () {
$LinkAs;
}
sub Mmp_LinkAsBase () {
$LinkAsBase;
}
sub Mmp_ExportLibrary () {
$ExportLibrary;
}
sub Mmp_NoExportLibrary () {
$NoExportLibrary;
}
sub Mmp_NewLib () {
$NewLib;
}
sub Mmp_Macros () {
@Macros;
}
sub Mmp_MmpFlag () {
\%MmpFlag;
}
sub Mmp_PlatTxt2D () {
@PlatTxt2D;
}
sub Mmp_ProcessPriority () {
$ProcessPriority;
}
sub Mmp_RamTargets () {
@RamTargets;
}
sub Mmp_ResourceStruct () {
\@ResourceStruct;
}
sub Mmp_RomTargets () {
@RomTargets;
}
sub Mmp_SourceStruct () {
\@SourceStruct;
}
sub Mmp_StackSize () {
$StackSize;
}
sub Mmp_StatLibList () {
@StatLibList;
}
sub Mmp_StdCpp () {
$StdCpp;
}
sub Mmp_NoStdCpp () {
$NoStdCpp;
}
sub Mmp_SysIncPaths () {
@SysIncPaths;
}
sub Mmp_Trg () {
$Trg;
}
sub Mmp_TrgType () {
\%TrgType;
}
sub Mmp_UidList () {
@UidList;
}
sub Mmp_UserIncPaths () {
@UserIncPaths;
}
sub Mmp_SrcDbg () {
$SrcDbg;
}
sub Mmp_WarningLevel() {
%Compiler;
}
sub Mmp_LinkerOptions() {
%LinkerOptions
}
sub Mmp_Version() {
%Version;
}
sub Mmp_SecureId() {
$SecureId;
}
sub Mmp_VendorId () {
$VendorId;
}
sub DecorateWithVersion($$) {
my ($name, %ver) = @_;
my $base = &Path_Split('Base', $name);
my $ext = &Path_Split('Ext', $name);
unless ($base =~ /\{(\d|a|b|c|d|e|f){8}\}$/i) {
$base .= &Genutl_VersionToFileAugment(%Version);
}
return "$base$ext";
}
sub Mmp_Replace() {
%Replace;
}
sub Mmp_SmpSafe() {
$SmpSafe;
}
sub Mmp_StringTable() {
\@StringTableStruct;
}
sub Mmp_ARMFPU() {
$ARMFPU;
}
sub Mmp_CheckSourceMMPMetaData() {
%CheckSourceMMPMetaData;
}
sub Mmp_CheckSourceMMPIncludes() {
%CheckSourceMMPIncludes;
}
sub Mmp_CodePagingTargetMode() {
$CodePagingTargetMode;
}
sub Mmp_DataPagingTargetMode() {
$DataPagingTargetMode;
}
sub Mmp_IsWideCharMain() {
$WideCharMain;
}
sub Mmp_IsDebuggable() {
$IsDebuggable;
}
sub Mmp_IsFeatureVariant() {
$FeatureVariant;
}
# Return the macros tested in the MMP file
sub Mmp_TestedMacros() {
return \%mmptestedMacrosHash;
}
1;