#!/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); | |
} |