blob: 1df474519ddd550b6bb2abea1b8fd9efe3895d38 [file] [log] [blame]
#!/usr/bin/perl
#
# Copyright Statement:
# --------------------
# This software is protected by Copyright and the information contained
# herein is confidential. The software may not be copied and the information
# contained herein may not be used or disclosed except with the written
# permission of MediaTek Inc. (C) 2005
#
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* objListGen.pm
#*
#* Project:
#* --------
#* Maui_Software
#*
#* Description:
#* ------------
#* This file help to handle the object list common operations.
#*
#*
#* Author:
#* -------
#* Ke-Ting Chen (mtk03141)
#*
#*****************************************************************************
package objListHelper;
#****************************************************************************
# Included Modules
#****************************************************************************
use strict;
use warnings;
BEGIN { push @INC, './pcore/tools/' } # add additional library path
use sysGenUtility;
use FileInfoParser;
use tools::pack_dep_gen;
#****************************************************************************
# History
#****************************************************************************
my $OBJ_LIST_HELPER_VERNO = " v1.03";
# v1.03: Move feature option evaluation functions to FileInfoParser.pm
# v1.02: Add checking check-in pattern function
# v1.01: Correct the compare object name algorithm
# v1.00: Phase in object list generate mechanism
#****************************************************************************
# Constants
#****************************************************************************
#****************************************************************************
# Variables
#****************************************************************************
#****************************************************************************
# subroutine: InputObjectListFromObjListFile
# description: Get the object list from the specified object list file.
# input: Input filename, object list ref
# output: Object list
# need init: No
#****************************************************************************
sub InputObjectListFromObjListFile
{
my $filename = shift;
my $objectListRef = shift;
my $category = $filename;
&ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
open my $input, "<$filename" or
&ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
while (<$input>)
{
chomp;
if (/^\s*; =+ (.+) =+/)
{
$category = $1;
}
elsif (/^\s*;/)
{
# Skip the comment line
}
elsif (/^\s*(\S+)\s+\((.*)\)/)
{
my $objectName = $1;
my @attributeArray = ($2 =~ /([\w|\+|\-]+)/g);
my %object = ("name" => $objectName, "attributes" => \@attributeArray, "category" => $category);
push @$objectListRef, \%object;
}
}
close $input;
}
#****************************************************************************
# subroutine: OutputObjectListToObjListFile
# description: Put the object list to the specified object list file.
# input: Output filename, object list ref, leading string, attribute string
# output: None
# need init: No
#****************************************************************************
sub OutputObjectListToObjListFile
{
my $filename = shift;
my $objectListRef = shift;
my $leadingString = shift;
my $attributeString = shift;
my $category = "";
$leadingString = "" unless defined $leadingString;
if (&IsManualModified($filename))
{
return 0;
}
&ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
open my $output, ">$filename" or
&ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
if (defined $objectListRef->[0] and exists $objectListRef->[0]{"category"})
{
$category = $objectListRef->[0]{"category"};
print $output "$leadingString; ====== $category ======\n";
}
foreach my $objectRef (@$objectListRef)
{
if ($objectRef->{"category"} ne $category)
{
$category = $objectRef->{"category"};
print $output "\n$leadingString; ====== $category ======\n";
}
print $output $leadingString."$objectRef->{name} (";
if (defined $attributeString)
{
print $output $attributeString;
}
else
{
print $output join(', ', @{$objectRef->{"attributes"}});
}
print $output ")\n";
}
close $output;
return 1;
}
#****************************************************************************
# subroutine: InputObjectListFromCSVFile
# description: Get the new object list from the specified csv file.
# input: Input filename, object list ref, makefile options hash ref
# output: Object list
# need init: No
#****************************************************************************
sub InputObjectListFromCSVFile
{
my $filename = shift;
my $objectListRef = shift;
my $makefileOptionsHashRef = shift;
&ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
open my $input, "<$filename" or
&ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
# Skip the first line which contains only the column header
<$input>;
while (<$input>)
{
chomp;
# Object Name,Attributes,Library Name,Category,Feature Option
{
my @entry = split(/,/);
unless (3 <= scalar(@entry) and
"" ne $entry[0] and
"" ne $entry[1] and
"" ne $entry[2])
{
&ErrorHandler("Incorrect CSV file format \"$_!\"", __FILE__, __LINE__);
}
$entry[3] = "" unless defined $entry[3];
$entry[4] = "" unless defined $entry[4];
# Check the feature option
if (($entry[4] ne "") and defined $makefileOptionsHashRef)
{
next unless (&FileInfo::EvaluateFeatureOptionCondition($entry[4], $makefileOptionsHashRef));
}
my @attributeArray = ($entry[1] =~ /([\w|\+|\-]+)/g);
my %object = ("name" => $entry[0],
"attributes" => \@attributeArray,
"library" => $entry[2],
"category" => $entry[3],
"feature_option" => $entry[4]);
push @$objectListRef, \%object;
}
}
close $input;
}
#****************************************************************************
# subroutine: InputObjectListFromLISInfo
# description: Get the new object list from the LIS info list.
# input: LIS info list ref, object list ref, attribute string, category
# output: Object list
# need init: No
#****************************************************************************
sub InputObjectListFromLISInfo
{
my $infoListRef = shift;
my $objectListRef = shift;
my $attributeString = shift;
my $category = shift;
$category = "" unless defined $category;
foreach my $info (@$infoListRef)
{
my @attributeArray = ($attributeString =~ /[\w|\+|\-]+/g);
my %object = ("name" => $info->{"name"},
"attributes" => \@attributeArray,
"library" => $info->{"library"},
"category" => $category,
"size" => $info->{"size"});
push @$objectListRef, \%object;
}
}
#****************************************************************************
# subroutine: OutputObjectListToCSVFile
# description: Put the object list to the specified object list file.
# input: Output filename, object list ref
# output: None
# need init: No
#****************************************************************************
sub OutputObjectListToCSVFile
{
my $filename = shift;
my $objectListRef = shift;
&ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
open my $output, ">$filename" or
&ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
# Print the column header
print $output "Object Name,Attributes,Library Name,Category,Feature Option\n";
foreach my $objectRef (@$objectListRef)
{
print $output "$objectRef->{name},(";
print $output join(' ', @{$objectRef->{"attributes"}});
print $output "),$objectRef->{library},$objectRef->{category},$objectRef->{feature_option}\n";
}
close $output;
}
#****************************************************************************
# subroutine: IsManualModified
# description: Check whether the file is manual modified.
# input: File path
# output: 1: the file is manual modified; 0: otherwise
# need init: No
#****************************************************************************
sub IsManualModified
{
my $filename = shift;
my $result = &sysUtil::HasCheckinHistory($filename);
if (defined $result and 1 == $result)
{
return 1;
}
else
{
return 0;
}
}
#****************************************************************************
# subroutine: SortObjectListByCategory
# description: Sort the object list by the category.
# input: Object list ref.
# output: Sorted object list
# need init: No
#****************************************************************************
sub SortObjectListByCategory
{
my $listRef = shift;
my %categoryListHash;
my @categorySequence;
foreach my $object (@$listRef)
{
my $category = $object->{"category"};
if (exists $categoryListHash{$category})
{
push @{$categoryListHash{$category}}, $object;
}
else
{
$categoryListHash{$category} = [$object];
push @categorySequence, $category;
}
}
@$listRef = ();
foreach my $category (@categorySequence)
{
push @$listRef, @{$categoryListHash{$category}};
}
}
#****************************************************************************
# subroutine: CompareObjectList
# description: Compare two object list.
# input: First object list, second object list
# output: 0 for equal; 1 for larger; -1 for smaller
# need init: No
#****************************************************************************
sub CompareObjectList
{
my $firstList = shift;
my $secondList = shift;
# Compare list entry number
if ((scalar(@$firstList) <=> scalar(@$secondList)) != 0)
{
return scalar(@$firstList) <=> scalar(@$secondList);
}
# Compare list entry name
my @sortedFirstList = sort {$a->{"name"} cmp $b->{"name"}} @$firstList;
my @sortedSecondList = sort {$a->{"name"} cmp $b->{"name"}} @$secondList;
for (my $i = 0; $i < scalar(@$firstList); ++$i)
{
if (($sortedFirstList[$i]{"name"} cmp $sortedSecondList[$i]{"name"}) != 0)
{
return ($sortedFirstList[$i]{"name"} cmp $sortedSecondList[$i]{"name"});
}
elsif (compareAttributeList($sortedFirstList[$i]{"attributes"}, $sortedSecondList[$i]{"attributes"}) != 0)
{
return compareAttributeList($sortedFirstList[$i]{"attributes"}, $sortedSecondList[$i]{"attributes"});
}
}
return 0;
}
#****************************************************************************
# subroutine: MergeAttributeList
# description: Merge the attribute list to the first attribute list.
# input: First list ref, second list ref
# output: Merged list in first list ref
# need init: No
#****************************************************************************
sub MergeAttributeList
{
my $firstRef;
my $secondRef;
my %resultHash;
foreach my $attribute (@$firstRef, @$secondRef)
{
$resultHash{$attribute} = 1;
}
if ($resultHash{"+RO"})
{
delete $resultHash{"+RO-CODE"} if (exists $resultHash{"+RO-CODE"});
delete $resultHash{"+RO-DATA"} if (exists $resultHash{"+RO-DATA"});
}
@$firstRef = sort compareAttribute keys %resultHash;
}
sub compareAttribute
{
my $first = shift;
my $second = shift;
my %attributeToNumber = ("+RO" => 0, "+RO-CODE" => 1, "+RO-DATA" => 2);
return $attributeToNumber{$first} <=> $attributeToNumber{$second};
}
sub compareAttributeList
{
my $firstList = shift;
my $secondList = shift;
# Compare list entry number
if ((scalar(@$firstList) <=> scalar(@$secondList)) != 0)
{
return scalar(@$firstList) <=> scalar(@$secondList);
}
for (my $i = 0; $i < scalar(@$firstList); ++$i)
{
if (compareAttribute($firstList->[$i], $secondList->[$i]) != 0)
{
return compareAttribute($firstList->[$i], $secondList->[$i]);
}
}
return 0;
}
#****************************************************************************
# subroutine: ChangeAttributeList
# description: Chagne the attribute list to the specified string.
# input: Object ref, attribute string
# output: Object ref
# need init: No
#****************************************************************************
sub ChangeAttributeList
{
my $objectRef = shift;
my $attributeString = shift;
my @attributeArray = ($attributeString =~ /([\w|\+|\-]+)/g);
$objectRef->{"attributes"} = \@attributeArray;
}
#****************************************************************************
# subroutine: ChangeObjectListAttributeList
# description: Chagne the attribute list of each object in the list to
# the specified string.
# input: Object ref, attribute string
# output: Object ref
# need init: No
#****************************************************************************
sub ChangeObjectListAttributeList
{
my $objectListRef = shift;
my $attributeString = shift;
foreach my $object (@$objectListRef)
{
&ChangeAttributeList($object, $attributeString);
}
}
#****************************************************************************
# subroutine: ChangeObjectListAttributeListByObjectList
# description: Chagne the attribute list of each object in the list by
# the specified object list.
# input: Target object ref, source object ref
# output: Target object ref
# need init: No
#****************************************************************************
sub ChangeObjectListAttributeListByObjectList
{
my $targetObjectListRef = shift;
my $sourceObjectListRef = shift;
my @matchList;
my @noMatchList;
&SplitObjectListByCheckList($targetObjectListRef, $sourceObjectListRef, \@matchList, \@matchList, \@noMatchList);
foreach my $object (@matchList)
{
if (exists $object->{"matchedObject"})
{
$object->{"attributes"} = \@{$object->{"matchedObject"}{"attributes"}};
}
}
}
#****************************************************************************
# subroutine: SplitObjectListByCheckList
# description: Split the source object list by check object list
# input: Source object list ref, check object list ref,
# match object list ref, match library list ref, match none list ref
# output: Match object list: the entry exactly match with the one in hash
# Match library list: the entry fall into the library in hash entry
# Match non list: match nothing
# note: This function will append a field "matched" to the objects in check list
#****************************************************************************
sub SplitObjectListByCheckList
{
my $sourceListRef = shift;
my $checkListRef = shift;
my $matchObjectListRef = shift;
my $matchLibraryListRef = shift;
my $matchNoneListRef = shift;
map { $_->{"matched"} = 0 } @$checkListRef;
foreach my $sourceObject (@$sourceListRef)
{
my $splitted = 0;
# Cannot use hash for fast search since there are evil wildcards...
foreach my $checkObject (@$checkListRef)
{
my $compareResult = compareObjectName($checkObject->{"name"}, $sourceObject->{"name"});
if (0 == $compareResult)
{
# Exactly match
push @$matchObjectListRef, $sourceObject;
$sourceObject->{"matchedObject"} = $checkObject;
$checkObject->{"matched"} = 1;
$splitted = 1;
last;
}
elsif (0 < $compareResult)
{
# Source object name is contained in the check object name
push @$matchObjectListRef, $sourceObject;
$sourceObject->{"matchedObject"} = $checkObject;
# Do not set the matched flag since they are not exactly the same
$splitted = 1;
last;
}
else
{
# Source object name is not contained in the check object name
# Check the library
if (isLibraryName($sourceObject->{"name"}))
{
# Source object is a library, and it can only be put in matchObjectList
next;
}
elsif ($sourceObject->{"library"} eq "Unknown")
{
# The library of the source object is unknown, push to match library list for safety
push @$matchLibraryListRef, $sourceObject;
$splitted = 1;
last;
}
else
{
# Source object is a true object
if (isLibraryName($checkObject->{"name"}))
{
# Check object is a library, check if source is belong to it
$compareResult = compareObjectName($checkObject->{"name"}, $sourceObject->{"library"});
if (0 <= $compareResult)
{
# Match to the library
push @$matchLibraryListRef, $sourceObject;
$sourceObject->{"matchedObject"} = $checkObject;
$splitted = 1;
last
}
}
}
} # if (0 == $compareResult)
} # foreach my $checkObject (@$checkListRef)
if (not $splitted)
{
# Matches nothing
push @$matchNoneListRef, $sourceObject;
}
} # foreach my $sourceObject (@$sourceListRef)
}
# Return 1 if the name is belong to a library
sub isLibraryName
{
my $name = shift;
$name = lc $name;
if ((substr($name, -4) eq ".lib") or (substr($name, -2) eq ".a"))
{
return 1;
}
else
{
return 0;
}
}
# Compare two object name with wildcard
sub compareObjectName
{
my $first = shift;
my $second = shift;
$first = lc $first;
$second = lc $second;
if ($first eq $second)
{
# Exactly match
return 0;
}
elsif ($first =~ m/\*/)
{
$first =~ s/\./\\./g; # Change . to \.
$first =~ s/\*/.\*/g; # Change to regular expression form
$second =~ s/\*//g; # Remove wildcard symbol
if ($second =~ m/$first/)
{
# Second is contained in first
return 1;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
#****************************************************************************
# subroutine: ErrorHandler
# description: Handle the post process error and output the error message.
# Note calling this function will lead program terminated.
# input: Message, source filename, line number
# output: None
# need init: No
#****************************************************************************
sub ErrorHandler
{
my ($message, $file, $line) = @_;
my $errorMessage = "OBJ LIST ERROR: $message at $file line $line\n";
print $errorMessage;
die $errorMessage;
}
1;
#============================================================================
# Not used but for backing-up
#============================================================================
#****************************************************************************
# subroutine: ChangeObjectListToHash
# description: Chagne the object list to hash form.
# input: Object list ref, output hash ref, start serial number
# output: Object list hash
# need init: No
#****************************************************************************
sub ChangeObjectListToHash
{
my $listRef = shift;
my $hashRef = shift;
my $serialNumber = shift;
$serialNumber = 0 unless defined $serialNumber;
foreach my $object (@$listRef)
{
my $key = GetObjectKey($object);
if (exists $hashRef->{$key})
{
mergeAttributeList($hashRef->{$key}->{"attributes"}, $object->{"attributes"});
}
else
{
$hashRef->{$key} = $object;
$object->{"matched"} = 0;
$object->{"serial"} = $serialNumber++;
}
}
return $serialNumber;
}
#****************************************************************************
# subroutine: GetObjectKey
# description: Get the object key used in object hash.
# input: Object ref
# output: Key of the object
# need init: No
#****************************************************************************
sub GetObjectKey
{
my $object = shift;
return "$object->{name}::$object->{library}";
}
#****************************************************************************
# subroutine: ChangeObjectHashToList
# description: Chagne the object hash to list form.
# input: Object hash ref, output list ref
# output: Object list
# need init: No
#****************************************************************************
sub ChangeObjectHashToList
{
my $hashRef = shift;
my $listRef = shift;
@$listRef = (sort {$a->{"serial"} <=> $b->{"serial"}} values %$hashRef);
}