blob: 1df474519ddd550b6bb2abea1b8fd9efe3895d38 [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001#!/usr/bin/perl
2#
3# Copyright Statement:
4# --------------------
5# This software is protected by Copyright and the information contained
6# herein is confidential. The software may not be copied and the information
7# contained herein may not be used or disclosed except with the written
8# permission of MediaTek Inc. (C) 2005
9#
10# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
11# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
12# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
13# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
14# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
15# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
16# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
17# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
18# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
19# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
20# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
21# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
22#
23# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
24# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
25# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
26# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
27# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
28#
29# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
30# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
31# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
32# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
33# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
34#
35#
36#*****************************************************************************
37#*
38#* Filename:
39#* ---------
40#* objListGen.pm
41#*
42#* Project:
43#* --------
44#* Maui_Software
45#*
46#* Description:
47#* ------------
48#* This file help to handle the object list common operations.
49#*
50#*
51#* Author:
52#* -------
53#* Ke-Ting Chen (mtk03141)
54#*
55#*****************************************************************************
56package objListHelper;
57#****************************************************************************
58# Included Modules
59#****************************************************************************
60use strict;
61use warnings;
62BEGIN { push @INC, './pcore/tools/' } # add additional library path
63use sysGenUtility;
64use FileInfoParser;
65use tools::pack_dep_gen;
66
67#****************************************************************************
68# History
69#****************************************************************************
70my $OBJ_LIST_HELPER_VERNO = " v1.03";
71 # v1.03: Move feature option evaluation functions to FileInfoParser.pm
72 # v1.02: Add checking check-in pattern function
73 # v1.01: Correct the compare object name algorithm
74 # v1.00: Phase in object list generate mechanism
75
76#****************************************************************************
77# Constants
78#****************************************************************************
79
80#****************************************************************************
81# Variables
82#****************************************************************************
83
84#****************************************************************************
85# subroutine: InputObjectListFromObjListFile
86# description: Get the object list from the specified object list file.
87# input: Input filename, object list ref
88# output: Object list
89# need init: No
90#****************************************************************************
91sub InputObjectListFromObjListFile
92{
93 my $filename = shift;
94 my $objectListRef = shift;
95 my $category = $filename;
96
97 &ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
98
99 open my $input, "<$filename" or
100 &ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
101
102 while (<$input>)
103 {
104 chomp;
105
106 if (/^\s*; =+ (.+) =+/)
107 {
108 $category = $1;
109 }
110 elsif (/^\s*;/)
111 {
112 # Skip the comment line
113 }
114 elsif (/^\s*(\S+)\s+\((.*)\)/)
115 {
116 my $objectName = $1;
117 my @attributeArray = ($2 =~ /([\w|\+|\-]+)/g);
118 my %object = ("name" => $objectName, "attributes" => \@attributeArray, "category" => $category);
119
120 push @$objectListRef, \%object;
121 }
122 }
123
124 close $input;
125}
126
127#****************************************************************************
128# subroutine: OutputObjectListToObjListFile
129# description: Put the object list to the specified object list file.
130# input: Output filename, object list ref, leading string, attribute string
131# output: None
132# need init: No
133#****************************************************************************
134sub OutputObjectListToObjListFile
135{
136 my $filename = shift;
137 my $objectListRef = shift;
138 my $leadingString = shift;
139 my $attributeString = shift;
140 my $category = "";
141
142 $leadingString = "" unless defined $leadingString;
143
144 if (&IsManualModified($filename))
145 {
146 return 0;
147 }
148
149 &ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
150
151 open my $output, ">$filename" or
152 &ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
153
154 if (defined $objectListRef->[0] and exists $objectListRef->[0]{"category"})
155 {
156 $category = $objectListRef->[0]{"category"};
157 print $output "$leadingString; ====== $category ======\n";
158 }
159
160 foreach my $objectRef (@$objectListRef)
161 {
162 if ($objectRef->{"category"} ne $category)
163 {
164 $category = $objectRef->{"category"};
165 print $output "\n$leadingString; ====== $category ======\n";
166 }
167
168 print $output $leadingString."$objectRef->{name} (";
169 if (defined $attributeString)
170 {
171 print $output $attributeString;
172 }
173 else
174 {
175 print $output join(', ', @{$objectRef->{"attributes"}});
176 }
177 print $output ")\n";
178 }
179
180 close $output;
181
182 return 1;
183}
184
185#****************************************************************************
186# subroutine: InputObjectListFromCSVFile
187# description: Get the new object list from the specified csv file.
188# input: Input filename, object list ref, makefile options hash ref
189# output: Object list
190# need init: No
191#****************************************************************************
192sub InputObjectListFromCSVFile
193{
194 my $filename = shift;
195 my $objectListRef = shift;
196 my $makefileOptionsHashRef = shift;
197
198 &ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
199
200 open my $input, "<$filename" or
201 &ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
202
203 # Skip the first line which contains only the column header
204 <$input>;
205
206 while (<$input>)
207 {
208 chomp;
209
210 # Object Name,Attributes,Library Name,Category,Feature Option
211 {
212 my @entry = split(/,/);
213 unless (3 <= scalar(@entry) and
214 "" ne $entry[0] and
215 "" ne $entry[1] and
216 "" ne $entry[2])
217 {
218 &ErrorHandler("Incorrect CSV file format \"$_!\"", __FILE__, __LINE__);
219 }
220
221 $entry[3] = "" unless defined $entry[3];
222 $entry[4] = "" unless defined $entry[4];
223
224 # Check the feature option
225 if (($entry[4] ne "") and defined $makefileOptionsHashRef)
226 {
227 next unless (&FileInfo::EvaluateFeatureOptionCondition($entry[4], $makefileOptionsHashRef));
228 }
229
230 my @attributeArray = ($entry[1] =~ /([\w|\+|\-]+)/g);
231 my %object = ("name" => $entry[0],
232 "attributes" => \@attributeArray,
233 "library" => $entry[2],
234 "category" => $entry[3],
235 "feature_option" => $entry[4]);
236 push @$objectListRef, \%object;
237 }
238 }
239
240 close $input;
241}
242
243#****************************************************************************
244# subroutine: InputObjectListFromLISInfo
245# description: Get the new object list from the LIS info list.
246# input: LIS info list ref, object list ref, attribute string, category
247# output: Object list
248# need init: No
249#****************************************************************************
250sub InputObjectListFromLISInfo
251{
252 my $infoListRef = shift;
253 my $objectListRef = shift;
254 my $attributeString = shift;
255 my $category = shift;
256
257 $category = "" unless defined $category;
258
259
260 foreach my $info (@$infoListRef)
261 {
262 my @attributeArray = ($attributeString =~ /[\w|\+|\-]+/g);
263 my %object = ("name" => $info->{"name"},
264 "attributes" => \@attributeArray,
265 "library" => $info->{"library"},
266 "category" => $category,
267 "size" => $info->{"size"});
268 push @$objectListRef, \%object;
269 }
270}
271
272#****************************************************************************
273# subroutine: OutputObjectListToCSVFile
274# description: Put the object list to the specified object list file.
275# input: Output filename, object list ref
276# output: None
277# need init: No
278#****************************************************************************
279sub OutputObjectListToCSVFile
280{
281 my $filename = shift;
282 my $objectListRef = shift;
283
284 &ErrorHandler("Undefined object list reference!", __FILE__, __LINE__) unless (defined $objectListRef);
285
286 open my $output, ">$filename" or
287 &ErrorHandler("Cannot open file $filename $!", __FILE__, __LINE__);
288
289 # Print the column header
290 print $output "Object Name,Attributes,Library Name,Category,Feature Option\n";
291
292 foreach my $objectRef (@$objectListRef)
293 {
294 print $output "$objectRef->{name},(";
295 print $output join(' ', @{$objectRef->{"attributes"}});
296 print $output "),$objectRef->{library},$objectRef->{category},$objectRef->{feature_option}\n";
297 }
298
299 close $output;
300}
301
302#****************************************************************************
303# subroutine: IsManualModified
304# description: Check whether the file is manual modified.
305# input: File path
306# output: 1: the file is manual modified; 0: otherwise
307# need init: No
308#****************************************************************************
309sub IsManualModified
310{
311 my $filename = shift;
312 my $result = &sysUtil::HasCheckinHistory($filename);
313
314 if (defined $result and 1 == $result)
315 {
316 return 1;
317 }
318 else
319 {
320 return 0;
321 }
322}
323
324#****************************************************************************
325# subroutine: SortObjectListByCategory
326# description: Sort the object list by the category.
327# input: Object list ref.
328# output: Sorted object list
329# need init: No
330#****************************************************************************
331sub SortObjectListByCategory
332{
333 my $listRef = shift;
334 my %categoryListHash;
335 my @categorySequence;
336
337 foreach my $object (@$listRef)
338 {
339 my $category = $object->{"category"};
340 if (exists $categoryListHash{$category})
341 {
342 push @{$categoryListHash{$category}}, $object;
343 }
344 else
345 {
346 $categoryListHash{$category} = [$object];
347 push @categorySequence, $category;
348 }
349 }
350
351 @$listRef = ();
352
353 foreach my $category (@categorySequence)
354 {
355 push @$listRef, @{$categoryListHash{$category}};
356 }
357}
358
359#****************************************************************************
360# subroutine: CompareObjectList
361# description: Compare two object list.
362# input: First object list, second object list
363# output: 0 for equal; 1 for larger; -1 for smaller
364# need init: No
365#****************************************************************************
366sub CompareObjectList
367{
368 my $firstList = shift;
369 my $secondList = shift;
370
371 # Compare list entry number
372 if ((scalar(@$firstList) <=> scalar(@$secondList)) != 0)
373 {
374 return scalar(@$firstList) <=> scalar(@$secondList);
375 }
376
377 # Compare list entry name
378 my @sortedFirstList = sort {$a->{"name"} cmp $b->{"name"}} @$firstList;
379 my @sortedSecondList = sort {$a->{"name"} cmp $b->{"name"}} @$secondList;
380
381 for (my $i = 0; $i < scalar(@$firstList); ++$i)
382 {
383 if (($sortedFirstList[$i]{"name"} cmp $sortedSecondList[$i]{"name"}) != 0)
384 {
385 return ($sortedFirstList[$i]{"name"} cmp $sortedSecondList[$i]{"name"});
386 }
387 elsif (compareAttributeList($sortedFirstList[$i]{"attributes"}, $sortedSecondList[$i]{"attributes"}) != 0)
388 {
389 return compareAttributeList($sortedFirstList[$i]{"attributes"}, $sortedSecondList[$i]{"attributes"});
390 }
391 }
392
393 return 0;
394}
395
396#****************************************************************************
397# subroutine: MergeAttributeList
398# description: Merge the attribute list to the first attribute list.
399# input: First list ref, second list ref
400# output: Merged list in first list ref
401# need init: No
402#****************************************************************************
403sub MergeAttributeList
404{
405 my $firstRef;
406 my $secondRef;
407
408 my %resultHash;
409
410 foreach my $attribute (@$firstRef, @$secondRef)
411 {
412 $resultHash{$attribute} = 1;
413 }
414
415 if ($resultHash{"+RO"})
416 {
417 delete $resultHash{"+RO-CODE"} if (exists $resultHash{"+RO-CODE"});
418 delete $resultHash{"+RO-DATA"} if (exists $resultHash{"+RO-DATA"});
419 }
420
421 @$firstRef = sort compareAttribute keys %resultHash;
422}
423
424sub compareAttribute
425{
426 my $first = shift;
427 my $second = shift;
428
429 my %attributeToNumber = ("+RO" => 0, "+RO-CODE" => 1, "+RO-DATA" => 2);
430
431 return $attributeToNumber{$first} <=> $attributeToNumber{$second};
432}
433
434sub compareAttributeList
435{
436 my $firstList = shift;
437 my $secondList = shift;
438
439 # Compare list entry number
440 if ((scalar(@$firstList) <=> scalar(@$secondList)) != 0)
441 {
442 return scalar(@$firstList) <=> scalar(@$secondList);
443 }
444
445 for (my $i = 0; $i < scalar(@$firstList); ++$i)
446 {
447 if (compareAttribute($firstList->[$i], $secondList->[$i]) != 0)
448 {
449 return compareAttribute($firstList->[$i], $secondList->[$i]);
450 }
451 }
452
453 return 0;
454}
455
456#****************************************************************************
457# subroutine: ChangeAttributeList
458# description: Chagne the attribute list to the specified string.
459# input: Object ref, attribute string
460# output: Object ref
461# need init: No
462#****************************************************************************
463sub ChangeAttributeList
464{
465 my $objectRef = shift;
466 my $attributeString = shift;
467
468 my @attributeArray = ($attributeString =~ /([\w|\+|\-]+)/g);
469
470 $objectRef->{"attributes"} = \@attributeArray;
471}
472
473#****************************************************************************
474# subroutine: ChangeObjectListAttributeList
475# description: Chagne the attribute list of each object in the list to
476# the specified string.
477# input: Object ref, attribute string
478# output: Object ref
479# need init: No
480#****************************************************************************
481sub ChangeObjectListAttributeList
482{
483 my $objectListRef = shift;
484 my $attributeString = shift;
485
486 foreach my $object (@$objectListRef)
487 {
488 &ChangeAttributeList($object, $attributeString);
489 }
490}
491
492#****************************************************************************
493# subroutine: ChangeObjectListAttributeListByObjectList
494# description: Chagne the attribute list of each object in the list by
495# the specified object list.
496# input: Target object ref, source object ref
497# output: Target object ref
498# need init: No
499#****************************************************************************
500sub ChangeObjectListAttributeListByObjectList
501{
502 my $targetObjectListRef = shift;
503 my $sourceObjectListRef = shift;
504
505 my @matchList;
506 my @noMatchList;
507
508 &SplitObjectListByCheckList($targetObjectListRef, $sourceObjectListRef, \@matchList, \@matchList, \@noMatchList);
509
510 foreach my $object (@matchList)
511 {
512 if (exists $object->{"matchedObject"})
513 {
514 $object->{"attributes"} = \@{$object->{"matchedObject"}{"attributes"}};
515 }
516 }
517}
518
519#****************************************************************************
520# subroutine: SplitObjectListByCheckList
521# description: Split the source object list by check object list
522# input: Source object list ref, check object list ref,
523# match object list ref, match library list ref, match none list ref
524# output: Match object list: the entry exactly match with the one in hash
525# Match library list: the entry fall into the library in hash entry
526# Match non list: match nothing
527# note: This function will append a field "matched" to the objects in check list
528#****************************************************************************
529sub SplitObjectListByCheckList
530{
531 my $sourceListRef = shift;
532 my $checkListRef = shift;
533
534 my $matchObjectListRef = shift;
535 my $matchLibraryListRef = shift;
536 my $matchNoneListRef = shift;
537
538 map { $_->{"matched"} = 0 } @$checkListRef;
539
540 foreach my $sourceObject (@$sourceListRef)
541 {
542 my $splitted = 0;
543
544 # Cannot use hash for fast search since there are evil wildcards...
545 foreach my $checkObject (@$checkListRef)
546 {
547 my $compareResult = compareObjectName($checkObject->{"name"}, $sourceObject->{"name"});
548 if (0 == $compareResult)
549 {
550 # Exactly match
551 push @$matchObjectListRef, $sourceObject;
552 $sourceObject->{"matchedObject"} = $checkObject;
553 $checkObject->{"matched"} = 1;
554 $splitted = 1;
555 last;
556 }
557 elsif (0 < $compareResult)
558 {
559 # Source object name is contained in the check object name
560 push @$matchObjectListRef, $sourceObject;
561 $sourceObject->{"matchedObject"} = $checkObject;
562 # Do not set the matched flag since they are not exactly the same
563 $splitted = 1;
564 last;
565 }
566 else
567 {
568 # Source object name is not contained in the check object name
569 # Check the library
570 if (isLibraryName($sourceObject->{"name"}))
571 {
572 # Source object is a library, and it can only be put in matchObjectList
573 next;
574 }
575 elsif ($sourceObject->{"library"} eq "Unknown")
576 {
577 # The library of the source object is unknown, push to match library list for safety
578 push @$matchLibraryListRef, $sourceObject;
579 $splitted = 1;
580 last;
581 }
582 else
583 {
584 # Source object is a true object
585 if (isLibraryName($checkObject->{"name"}))
586 {
587 # Check object is a library, check if source is belong to it
588 $compareResult = compareObjectName($checkObject->{"name"}, $sourceObject->{"library"});
589 if (0 <= $compareResult)
590 {
591 # Match to the library
592 push @$matchLibraryListRef, $sourceObject;
593 $sourceObject->{"matchedObject"} = $checkObject;
594 $splitted = 1;
595 last
596 }
597 }
598 }
599 } # if (0 == $compareResult)
600 } # foreach my $checkObject (@$checkListRef)
601
602 if (not $splitted)
603 {
604 # Matches nothing
605 push @$matchNoneListRef, $sourceObject;
606 }
607 } # foreach my $sourceObject (@$sourceListRef)
608}
609
610# Return 1 if the name is belong to a library
611sub isLibraryName
612{
613 my $name = shift;
614 $name = lc $name;
615
616 if ((substr($name, -4) eq ".lib") or (substr($name, -2) eq ".a"))
617 {
618 return 1;
619 }
620 else
621 {
622 return 0;
623 }
624}
625
626# Compare two object name with wildcard
627sub compareObjectName
628{
629 my $first = shift;
630 my $second = shift;
631
632 $first = lc $first;
633 $second = lc $second;
634
635 if ($first eq $second)
636 {
637 # Exactly match
638 return 0;
639 }
640 elsif ($first =~ m/\*/)
641 {
642 $first =~ s/\./\\./g; # Change . to \.
643 $first =~ s/\*/.\*/g; # Change to regular expression form
644 $second =~ s/\*//g; # Remove wildcard symbol
645
646 if ($second =~ m/$first/)
647 {
648 # Second is contained in first
649 return 1;
650 }
651 else
652 {
653 return -1;
654 }
655 }
656 else
657 {
658 return -1;
659 }
660}
661
662#****************************************************************************
663# subroutine: ErrorHandler
664# description: Handle the post process error and output the error message.
665# Note calling this function will lead program terminated.
666# input: Message, source filename, line number
667# output: None
668# need init: No
669#****************************************************************************
670sub ErrorHandler
671{
672 my ($message, $file, $line) = @_;
673
674 my $errorMessage = "OBJ LIST ERROR: $message at $file line $line\n";
675 print $errorMessage;
676
677 die $errorMessage;
678}
679
6801;
681
682#============================================================================
683# Not used but for backing-up
684#============================================================================
685
686#****************************************************************************
687# subroutine: ChangeObjectListToHash
688# description: Chagne the object list to hash form.
689# input: Object list ref, output hash ref, start serial number
690# output: Object list hash
691# need init: No
692#****************************************************************************
693sub ChangeObjectListToHash
694{
695 my $listRef = shift;
696 my $hashRef = shift;
697 my $serialNumber = shift;
698
699 $serialNumber = 0 unless defined $serialNumber;
700
701 foreach my $object (@$listRef)
702 {
703 my $key = GetObjectKey($object);
704 if (exists $hashRef->{$key})
705 {
706 mergeAttributeList($hashRef->{$key}->{"attributes"}, $object->{"attributes"});
707 }
708 else
709 {
710 $hashRef->{$key} = $object;
711 $object->{"matched"} = 0;
712 $object->{"serial"} = $serialNumber++;
713 }
714 }
715
716 return $serialNumber;
717}
718
719#****************************************************************************
720# subroutine: GetObjectKey
721# description: Get the object key used in object hash.
722# input: Object ref
723# output: Key of the object
724# need init: No
725#****************************************************************************
726sub GetObjectKey
727{
728 my $object = shift;
729
730 return "$object->{name}::$object->{library}";
731}
732
733#****************************************************************************
734# subroutine: ChangeObjectHashToList
735# description: Chagne the object hash to list form.
736# input: Object hash ref, output list ref
737# output: Object list
738# need init: No
739#****************************************************************************
740sub ChangeObjectHashToList
741{
742 my $hashRef = shift;
743 my $listRef = shift;
744
745 @$listRef = (sort {$a->{"serial"} <=> $b->{"serial"}} values %$hashRef);
746}