blob: d88da72464c138599e82b39c472c830292a19854 [file] [log] [blame]
rjw6c1fd8f2022-11-30 14:33:01 +08001#!/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) 2006
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#* Filename:
38#* ---------
39#* FileInfoParser.pm
40#*
41#* Project:
42#* --------
43#*
44#*
45#* Description:
46#* ------------
47#* This module collects the subroutines for common utility.
48#*
49#*
50#* Author:
51#* -------
52#* Carl Kao (mtk08237)
53#*
54#****************************************************************************/
55use strict;
56#use warnings;
57BEGIN { push @INC, './pcore/tools/' } # add additional library path
58#--------------------------------------------------------------------------------------------------------------
59package BuildOPT;
60#****************************************************************************
61# Constant
62#****************************************************************************
63use constant CMPL => 0;
64use constant REL => 1;
65#--------------------------------------------------------------------------------------------------------------
66package FileInfo;
67use constant SHARED_REGION_SIZE => "SHARED_REGION_SIZE";
68use constant PCORE_LV_SIZE => "PCORE_LV_SIZE";
69
70use sysGenUtility; #pm file name without case sensitivity
71use CommonUtility;
72#****************************************************************************
73# Constants
74#****************************************************************************
75my $FILEINFOPARSER_VERNO = " a0.01";
76 # a0.01 , 2016/11/21, Tero, Mode parsing fixed
77 # u0.18 , 2016/08/01, Tero, L1Core and Copro info removed
78 # u0.17 , 2016/01/31, Tero, Fix compiler option parsing bug in EvaluateCompileOption()
79 # u0.16 , 2015/07/03, Carl, Call GetDefaultSharedMemorySize to get default shared memory size
80 # u0.15 , 2015/06/23, Carl, Refine GetSharedMemorySize. It includes dsp tx/rx section now
81 # u0.14 , 2015/06/22, Carl, Decrease shared region size (in 1st linking time) from 96 MB to 80 MB
82 # u0.13 , 2015/06/22, Carl, Decrease shared region size (in 1st linking time) from 112 MB to 96 MB
83 # u0.12 , 2015/05/19, Carl, Increase shared region size (in 1st linking time) from 80 MB to 112 MB
84 # u0.11 , 2015/04/17, Carl, Increase shared region size (in 1st linking time) from 48 MB to 80 MB
85 # u0.10 , 2015/02/06, Carl, disable isSupportedToAdjustLoadView for ESL COSIM
86 # u0.09 , 2015/01/06, Carl, lds refinement: 1) auto adjust shared region size, 2) reserve pcore, l1core SWLA space
87 # u0.08 , 2014/22/22, Carl, Support L2SRAM section (in L1CORE)
88 # u0.07 , 2014/08/20, Carl, refine l1core dump region
89 # u0.06 , 2014/08/19, Carl, add constant value for l1core rector vector load view
90 # u0.05 , 2014/07/31, Carl, add constant value for dump l1core region
91 # ...
92 # m0.14 , 2013/12/24, Support is_with_AP
93 # m0.13 , 2013/06/28, Ignore MD5 in MDSYS option
94 # m0.12 , 2013/06/25, Support Copro related query and combined cmp_option+mkfile parsing and query
95 # m0.11 , 2013/05/28, Support to evaluate compiler option
96 # m0.10 , 2012/11/16, Support is_MAIN_CODE_NEED_GFH
97 # m0.09 , 2013/03/22, Support parsing informake.log
98 # m0.08 , 2012/01/14, Support basic query functions more flexible
99 # m0.07 , 2012/10/19, Support is_XBOOTING, is_HostedDongle, is_RNDISDongle
100 # m0.06 , 2012/09/18, Fix MakeFile mode parsing
101 # m0.05 , 2012/08/17, Support GetChip()
102 # m0.04 , 2012/08/06, Add more common functions and ParseDefinition()
103 # m0.03 , 2012/07/26, Support is_NonSPNOR()
104 # m0.02 , 2012/05/28, Support path and filename case sensitive on Linux
105 # v0.07 , 2012/05/13, Move is_NOR from sysgenUtility to here and support general query
106 # m0.01 , 2012/05/09, Provide GetCompiler()
107 # v0.06 , 2012/05/08, Copy parseFeatureOptionCondition
108 # and EvaluateFeatureOptionCondition from objListHelper.pm to here
109 # v0.05 , 2012/05/08, Query is_SmartPhone
110 # v0.04 , 2012/01/30, To provide CUSTOMER and MODE in %MAKEFILE_OPTIONS
111 # v0.03 , 2011/12/17, Fix parsing MakeFile
112 # v0.02 , 2011/11/01, Remove $$ to support Perl v5.12.*
113 # v0.01 , 2011/09/21, Initial revision
114
115#****************************************************************************
116# Global variable
117#****************************************************************************
118my $g_MAKEFILE_href = undef;
119#****************************************************************************
120# oo >>> Finished
121#****************************************************************************
122return 1;
123
124sub PreProcess
125{
126 my ($MAKE_FILE, $mk_href, $INFOMAKE, $CmplOpt_href, $RelInfo_href, $bDie) = @_;
127 my $bResult = 1;
128 if(!BuildInfo::Parse_InfoMakeLog($INFOMAKE, $CmplOpt_href, $RelInfo_href))
129 {
130 $bResult = 0;
131 FileInfoParser_die("Parse infomake.log failed")if($bDie);
132 }
133 if(!FileInfo::Parse_MAKEFILE($MAKE_FILE, $mk_href))
134 {
135 $bResult = 0;
136 FileInfoParser_die("Parse MakeFile failed")if($bDie);
137 }
138 return $bResult;
139}
140
141#****************************************************************************
142# subroutine: Parse_MAKEFILE
143# input: 1. MAKEFILE path
144# 2. a Hash to contain MAKEFILE information.
145# output: 1=Parse successfully, 0 or die= Parse failed.
146# sample code: my %MAKEFILE_OPTIONS;
147# &FileInfo::Parse_MAKEFILE($MAKEFILE_Path, \%MAKEFILE_OPTIONS);
148#****************************************************************************
149
150sub Parse_MAKEFILE
151{
152 my ($strMAKEFILE_Path, $Info_href) = @_;
153 my $bResult = 0;
154 if(-e $strMAKEFILE_Path)
155 {
156 open (FILE_HANDLE, $strMAKEFILE_Path) or &FileInfoParser_die("Cannot open $strMAKEFILE_Path\n", __FILE__, __LINE__);
157 while (<FILE_HANDLE>)
158 {
159 if ((/^([^\#]*)\#?.*/) && ($1 =~ /^(\w+)\s*=\s*(.*\S)\s*$/))
160 {
161 my $keyname = lc($1);
162 #defined($Info_href->{$keyname}) && warn "$1 redefined in $strMAKEFILE_Path!\n";
163 $Info_href->{$keyname} = uc($2);
164 $keyname = uc($1);
165 #defined($Info_href->{$keyname}) && warn "$1 redefined in $strMAKEFILE_Path!\n";
166 $Info_href->{$keyname} = uc($2);
167 $bResult = 1;
168 }
169 }
170 close FILE_HANDLE;
171 if ($strMAKEFILE_Path =~ /(\w+)_(\w+)\((\w+)\).mak/i)
172 {
173 $Info_href->{'MODE'} = uc($3);
174 $Info_href->{'mode'} = uc($3);
175 }
176 $g_MAKEFILE_href = $Info_href;
177 }
178 else
179 {
180 &FileInfoParser_die("$strMAKEFILE_Path: NOT exist!", __FILE__, __LINE__);
181 }
182 return $bResult;
183}
184
185sub GetMakeFileRef
186{
187 my ($strMAKEFILE_Path) = @_;
188 if(!defined $g_MAKEFILE_href)
189 {
190 my %MakeFileOption;
191 &Parse_MAKEFILE($strMAKEFILE_Path, \%MakeFileOption);
192 }
193 return $g_MAKEFILE_href;
194}
195sub is
196{
197 my ($strKey, $strValue, $MakeFile_ref) = @_;
198 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
199 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
200 my $bEqual = 0;
201 if(exists $MakeFile_ref->{uc($strKey)} and uc($MakeFile_ref->{uc($strKey)}) eq uc($strValue))
202 {
203 $bEqual = 1;
204 }
205 return $bEqual;
206}
207sub find
208{
209 my ($strKey, $strValue, $MakeFile_ref) = @_;
210 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
211 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
212 my $bFound = 0;
213 if(exists $MakeFile_ref->{uc($strKey)} and $MakeFile_ref->{uc($strKey)} =~ /$strValue/)
214 {
215 $bFound = 1;
216 }
217 return $bFound;
218}
219sub isnot
220{
221 my ($strKey, $strValue, $MakeFile_ref) = @_;
222 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
223 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
224 my $bNotEqual = 0;
225 if(exists $MakeFile_ref->{uc($strKey)} and uc($MakeFile_ref->{uc($strKey)}) ne uc($strValue))
226 { #exist but not equal
227 $bNotEqual = 1;
228 }
229 return $bNotEqual;
230}
231sub get
232{
233 my ($strKey, $MakeFile_ref) = @_;
234 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
235 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
236 my $Value = undef;
237 if(exists $MakeFile_ref->{uc($strKey)})
238 {
239 $Value = $MakeFile_ref->{uc($strKey)};
240 }
241 elsif(exists $MakeFile_ref->{$strKey})
242 {
243 $Value = $MakeFile_ref->{$strKey};
244 }
245 return $Value;
246}
247sub ParseDefinition
248{
249 my ($strFilePath, $Hash_ref, $bAllowDuplicated) = @_;
250 my $content = &CommonUtil::GetFileContent($strFilePath);
251 #strip comments
252 $content =~ s/\/\/(.+)//g;
253 $content =~s#/\*[^*]*\*+([^/*][^*]*\*+)*/|([^/"']*("[^"\\]*(\\[\d\D][^"\\]*)*"[^/"']*|'[^'\\]*(\\[\d\D][^'\\]*)*'[^/"']*|/+[^*/][^/"']*)*)#$2#g;
254
255 my @lines = split(/\n|\r/, $content);
256 my $nDuplicatedIndex=0;
257 foreach my $line (@lines)
258 {
259 if ($line =~ /#define\s+(\w+)\s+\((.*)\)\s*$/ || $line =~ /#define\s+(\w+)\s+(\S*)\s*$/)
260 {
261 my $option = $1;
262 my $value = $2;
263 &FileInfoParser_die("$strFilePath: $option redefined in $strFilePath!", __FILE__, __LINE__)
264 if (!$bAllowDuplicated and defined($Hash_ref->{$option}));
265 if (!defined $value)
266 {
267 $Hash_ref->{$option} = 'TRUE';
268 $Hash_ref->{uc($option)} = 'TRUE';
269 $Hash_ref->{lc($option)} = 'TRUE';
270 }
271 else
272 {
273 $Hash_ref->{$option} = $value;
274 $Hash_ref->{uc($option)} = $value;
275 $Hash_ref->{lc($option)} = $value;
276 }
277 }
278 }
279 close (FILE_HANDLE);
280}
281
282
283#****************************************************************************
284# subroutine: is_SmartPhone - Query if it belongs smart phone project
285# Input: x
286# Output: 1=it's SmartPhone, others=not SmartPhone
287#****************************************************************************
288sub is_SmartPhone
289{
290 my ($MakeFile_ref) = @_;
291 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
292 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
293 my $bIsSmartPhone = 0;
294 if( exists $MakeFile_ref->{SMART_PHONE_CORE} and $MakeFile_ref->{SMART_PHONE_CORE} ne "NONE" ) #NONE = feature phone
295 {
296 $bIsSmartPhone = 1;
297 }
298 return $bIsSmartPhone;
299}
300
301#****************************************************************************
302# subroutine: is_with_AP - Query if it is paired with AP
303# Input: x
304# Output: 1=it's paired with AP, others=other combination
305#****************************************************************************
306sub is_with_AP
307{
308 my ($MakeFile_ref) = @_;
309 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
310 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
311 my $bIsWithAP = 0;
312 if( exists $MakeFile_ref->{SMART_PHONE_CORE} and $MakeFile_ref->{SMART_PHONE_CORE} =~/ANDROID_MODEM/i )
313 {
314 $bIsWithAP = 1;
315 }
316 return $bIsWithAP;
317}
318
319
320#****************************************************************************
321# subroutine: is_NOR - Query if it's NOR flash
322# Input: \%MAKEFILE_OPTION
323# Output: 0=not NOR, 1=NOR
324#****************************************************************************
325sub is_NOR
326{
327 my ($MAKEFILE_ref) = @_;
328 $MAKEFILE_ref = $g_MAKEFILE_href if (!defined $MAKEFILE_ref);
329 &NoMakeFile_die($MAKEFILE_ref, __FILE__, __LINE__);
330 my $bNOR = 1; # 0=not NOR, 1= NOR
331 if((exists $MAKEFILE_ref->{'nand_flash_booting'} and $MAKEFILE_ref->{'nand_flash_booting'} ne 'NONE')
332 or (exists $MAKEFILE_ref->{'emmc_booting'} and $MAKEFILE_ref->{'emmc_booting'} ne 'NONE'))
333 {
334 $bNOR = 0;
335 }
336 return $bNOR;
337}
338#****************************************************************************
339# subroutine: is_NonSPNOR - Query if it's not nand flash and not smart_phone project
340# Input: \%MAKEFILE_OPTION
341# Output: 0=not NOR, 1=NOR
342#****************************************************************************
343sub is_NonSPNOR
344{
345 my ($MAKEFILE_ref) = @_;
346 return (&is_NOR($MAKEFILE_ref) and !&is_SmartPhone($MAKEFILE_ref));
347}
348
349#****************************************************************************
350# subroutine: is_BuiltWithCopro - Query if it's built with copro
351# Input: \%MAKEFILE_OPTION, \%Compile_OPTION
352# Output: 0=not building with copro, 1=building with containing copro now
353#****************************************************************************
354sub is_BuiltWithCopro
355{
356 my ($MAKEFILE_ref, $CMPL_href) = @_;
357 my $bBuiltWithCopro = 0;
358 $bBuiltWithCopro = 1 if(is("MD_OFFLOAD_COPRO", "ARM7EJ-S", $MAKEFILE_ref)
359 and !BuildInfo::exist(BuildOPT::CMPL, "NEED_BUILD_MD_OFFLOAD_COPRO", $CMPL_href));
360 return $bBuiltWithCopro;
361}
362#****************************************************************************
363# subroutine: is_Copro - Query if it's COPRO
364# Input: \%MAKEFILE_OPTION, \%Compile_OPTION
365# Output: 0=not copro, 1=it's copro
366#****************************************************************************
367sub is_Copro
368{
369 my ($MAKEFILE_ref, $CMPL_href) = @_;
370 my $bCopro = 0;
371 $bCopro = 1 if(is("MD_OFFLOAD_COPRO", "ARM7EJ-S", $MAKEFILE_ref)
372 and BuildInfo::exist(BuildOPT::CMPL, "NEED_BUILD_MD_OFFLOAD_COPRO", $CMPL_href));
373 return $bCopro;
374}
375
376#****************************************************************************
377# subroutine: is_MAIN_CODE_NEED_GFH - Query if it's MAIN_CODE_NEED_GFH:
378# SMART_PHONE_CORE != NONE && X_BOOTING==NONE => MAIN_CODE_NEED_GFH = FALSE
379# Input: \%MAKEFILE_OPTION
380# Output: 0=no GFH, 1=having GFH
381#****************************************************************************
382sub is_MAIN_CODE_NEED_GFH
383{
384 my ($bb, $MAKEFILE_ref) = @_;
385 $MAKEFILE_ref = $g_MAKEFILE_href if (!defined $MAKEFILE_ref);
386 &NoMakeFile_die($MAKEFILE_ref, __FILE__, __LINE__);
387 my $bNEED_GFH = 0;
388 if(&sysUtil::is_sv5($bb))
389 {
390 $bNEED_GFH = 1;
391 if(&is_SmartPhone($MAKEFILE_ref) && &is("X_BOOTING", "NONE", $MAKEFILE_ref) )
392 {
393 $bNEED_GFH = 0;
394 }
395 }
396 return $bNEED_GFH;
397}
398
399#****************************************************************************
400# subroutine: is_XBOOTING - Query if it's X_BOOTING: X_BOOTING != NONE
401# Input: \%MAKEFILE_OPTION
402# Output: 0=not X BOOTING, 1=X BOOTING
403#****************************************************************************
404sub is_XBOOTING
405{
406 my ($MAKEFILE_ref) = @_;
407 $MAKEFILE_ref = $g_MAKEFILE_href if (!defined $MAKEFILE_ref);
408 &NoMakeFile_die($MAKEFILE_ref, __FILE__, __LINE__);
409 my $bX = 0;
410 $bX = 1 if(&isnot("X_BOOTING", "NONE"));
411 return $bX;
412}
413
414#****************************************************************************
415# subroutine: is_HostedDongle - Query if it's HostedDongle
416# SMART_PHONE_CORE=MODEM_HOST and X_BOOTING=NONE
417# Input: \%MAKEFILE_OPTION
418# Output: 0=not Hosted dongle, 1=Hosted dongle
419#****************************************************************************
420sub is_HostedDongle
421{
422 my ($MAKEFILE_ref) = @_;
423 $MAKEFILE_ref = $g_MAKEFILE_href if (!defined $MAKEFILE_ref);
424 &NoMakeFile_die($MAKEFILE_ref, __FILE__, __LINE__);
425 my $bX = 0;
426 $bX = 1 if(&is("SMART_PHONE_CORE", "MODEM_HOST") and !&is_XBOOTING());
427 return $bX;
428}
429
430
431#****************************************************************************
432# subroutine: is_RNDISDongle - Query if it's RNDIS Dongle
433# (is smartphone but SMART_PHONE_CORE != MODEM_HOST) and X_BOOTING=NONE
434# Input: \%MAKEFILE_OPTION
435# Output: 0=not RNDIS, 1=RNDIS
436#****************************************************************************
437sub is_RNDISDongle
438{
439 my ($MAKEFILE_ref) = @_;
440 $MAKEFILE_ref = $g_MAKEFILE_href if (!defined $MAKEFILE_ref);
441 &NoMakeFile_die($MAKEFILE_ref, __FILE__, __LINE__);
442 my $bX = 0;
443 $bX = 1 if(&is_SmartPhone() and !&is_XBOOTING() and !is_HostedDongle());
444 return $bX;
445}
446
447#****************************************************************************
448# subroutine: GetCompiler()
449# Input: \%MAKEFILE_OPTION
450# Output: Should be "GCC" or "RVCT" in string
451#****************************************************************************
452sub GetCompiler
453{
454 my ($MakeFile_ref) = @_;
455 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
456 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
457 my $strCompiler = undef;
458 $strCompiler = uc($MakeFile_ref->{COMPILER}) if(exists $MakeFile_ref->{COMPILER});
459 &FileInfoParser_die("Unsupported ToolChain!\n", __FILE__, __LINE__) if(($strCompiler ne "GCC") and ($strCompiler ne "RVCT"));
460 return $strCompiler;
461}
462#****************************************************************************
463# subroutine: GetChip()
464# Input: \%MAKEFILE_OPTION
465# \%COMPILER_OPTION
466# Output: string (e.g. MT6280 or MT6280_XX)
467#****************************************************************************
468sub GetChip
469{
470 my ($MakeFile_ref, $CMPL_href) = @_;
471 $MakeFile_ref = $g_MAKEFILE_href if (!defined $MakeFile_ref);
472 &NoMakeFile_die($MakeFile_ref, __FILE__, __LINE__);
473 my $strChip = undef;
474 $strChip = uc($MakeFile_ref->{PLATFORM}) if(exists $MakeFile_ref->{PLATFORM});
475 $strChip .= "_".uc($MakeFile_ref->{MDSYS}) if(exists $MakeFile_ref->{MDSYS} and $MakeFile_ref->{MDSYS} !~/none|md5/i);
476 $strChip .= "_COPRO" if(is_Copro($MakeFile_ref, $CMPL_href));
477 return $strChip;
478}
479
480#****************************************************************************
481# subroutine: GetSharedMemorySize
482# description: return shared region size
483# input: N/A
484# output: size of SHARED_REGION_SIZE in ~copro_info.tmp or default value (inculde dsp tx/rx sections)
485# need init: No
486#****************************************************************************
487sub GetSharedMemorySize
488{
489 my $nSharedRegionEnd = &FileInfo::get(SHARED_REGION_SIZE);
490 return ( 0==$nSharedRegionEnd ? &sysUtil::GetDefaultSharedMemorySize(&GetChip()) : $nSharedRegionEnd );
491}
492
493#****************************************************************************
494# subroutine: EvaluateFeatureOptionCondition
495# description: Evaluate the feature option condition.
496# input: Feature option condition(string), makefile options hash ref
497# output: 1: true, 0: false
498# need init: No
499#****************************************************************************
500sub EvaluateFeatureOptionCondition
501{
502 my $condition = shift;
503 my $makefileOptionsRef = shift;
504
505 my @expressionTree;
506 my @stack;
507
508 # Transform the condition to expression tree in postfix form
509 &parseFeatureOptionCondition($condition, \@expressionTree);
510
511 # Evaluate the expression tree
512 foreach my $token (@expressionTree)
513 {
514 if ($token eq "&&" or $token eq "||")
515 {
516 my $second = pop(@stack);
517 my $first = pop(@stack);
518 push (@stack, eval "$first $token $second");
519 }
520 elsif ($token eq "=")
521 {
522 my $second = pop(@stack);
523 my $first = pop(@stack);
524 my $value = $makefileOptionsRef->{$first};
525 $value = "" unless defined $value;
526 if ($value eq $second)
527 {
528 push (@stack, 1);
529 }
530 else
531 {
532 push (@stack, 0);
533 }
534 }
535 elsif ($token eq "!")
536 {
537 my $first = pop(@stack);
538 if ($first == 1)
539 {
540 push (@stack, 0);
541 }
542 else
543 {
544 push (@stack, 1);
545 }
546 }
547 else
548 {
549 push @stack, $token;
550 }
551 }
552 &FileInfoParser_die("Incorrect syntax of feature option condition \"$condition\"", __FILE__, __LINE__)
553 unless (1 == @stack);
554
555 return $stack[0];
556}
557
558#****************************************************************************
559# subroutine: parseFeatureOptionCondition
560# description: Parse the feature option condition to postfix form.
561# input: Feature option condition, expression tree ref
562# output: Expression tree
563# need init: No
564#****************************************************************************
565sub parseFeatureOptionCondition
566{
567 my $condition = shift;
568 my $expressionTreeRef = shift;
569 my $conditionNoSpace = $condition;
570 $conditionNoSpace =~ s/ //g;
571
572 my @tokens = split(/(=|\(|\)|&&|\|\||!)/, $conditionNoSpace);
573 my @stack;
574
575 # For error checking
576 my $parenthesis = 0;
577 my $operand = 0;
578 my $operator = 0;
579
580 foreach my $token (@tokens)
581 {
582 if ($token eq "")
583 {
584 # Skip empty token
585 next;
586 }
587 elsif ($token eq "(")
588 {
589 push @stack, $token;
590 ++$parenthesis;
591 }
592 elsif ($token eq ")")
593 {
594 &FileInfoParser_die("Incorrect syntax of feature option condition \"$condition\"", __FILE__, __LINE__)
595 unless (0 < $parenthesis);
596 my $temp = pop(@stack);
597
598 &FileInfoParser_die("Incorrect syntax of feature option condition \"$condition\"", __FILE__, __LINE__)
599 if ($temp eq "(");
600
601 do
602 {
603 push @$expressionTreeRef, $temp;
604 $temp = pop(@stack);
605 } while ($temp ne "(");
606
607 --$parenthesis;
608 }
609 elsif ($token eq "=" or $token eq "&&" or $token eq "||" or $token eq "!")
610 {
611 my $needLoop = 0;
612
613 do
614 {
615 if (0 == scalar(@stack) or $stack[-1] eq "(")
616 {
617 # Stack is empty or stack top eqals to (
618 push @stack, $token;
619 $needLoop = 0;
620 }
621 elsif (0 < compareFeatureOptionOperator($stack[-1], $token))
622 {
623 # Stack top has higher priority than current token
624 push @stack, $token;
625 $needLoop = 0;
626 }
627 else
628 {
629 push @$expressionTreeRef, pop(@stack);
630 $needLoop = 1;
631 }
632 } while ($needLoop);
633
634 $operator += 1 unless ($token eq "!");
635 }
636 elsif ($token =~ /\w+/)
637 {
638 # Operand
639 push @$expressionTreeRef, $token;
640 $operand += 1;
641 }
642 else
643 {
644 &FileInfoParser_die("Incorrect syntax of feature option condition \"$condition\"", __FILE__, __LINE__);
645 }
646 }
647
648 &FileInfoParser_die("Incorrect syntax of feature option condition \"$condition\"", __FILE__, __LINE__)
649 unless ($operator == ($operand - 1) and 0 == $parenthesis);
650
651 push @$expressionTreeRef, reverse(@stack);
652}
653
654sub compareFeatureOptionOperator
655{
656 my $first = shift;
657 my $second = shift;
658 my %operatorToNumber = ("=" => 0, "!" => 1, "&&" => 2, "||" => 2);
659
660 return $operatorToNumber{$first} <=> $operatorToNumber{$second};
661}
662
663#****************************************************************************
664# subroutine: FileInfoParser_die
665# sample code: (message, __FILE__, __LINE__)
666# input: $error_msg, $file, $line_no
667#****************************************************************************
668sub FileInfoParser_die
669{
670 my ($error_msg, $file, $line_no) = @_;
671 my $pack_name = undef;
672 if(!defined $file or !defined $line_no)
673 {
674 ($pack_name, $file, $line_no) = caller;
675 }
676 &sysUtil::error_handler($error_msg, $file, $line_no, 'ProjectMakeFileParser');
677}
678sub NoMakeFile_die
679{
680 my ($MAKEFILE_ref, $file, $line_no) = @_;
681 &FileInfoParser_die("Please parse project makefile by FileInfo::Parse_MAKEFILE() before using it.", $file, $line_no)
682 if(!defined $MAKEFILE_ref);
683}
684
685package BuildInfo;
686#****************************************************************************
687# Global variable
688#****************************************************************************
689my $g_CmplOpt_href = undef; # compiler option
690my $g_RelInfo_href = undef; # release info
691#****************************************************************************
692# Subroutine
693#****************************************************************************
694#****************************************************************************
695# subroutine: Parse_InfoMakeLog
696# input: 1. Infomake.log path
697# 2. a Hash reference to contain CompilerOption information.
698# 3. a Hash reference to contain Release information.
699# output: 1=Parse successfully, 0 or die= Parse failed.
700# sample code: my %CmplOption;
701# my %RelOption;
702# BuildInfo::Parse_InfoMakeLog($infomake_path, \%CmplOption, \%RelOption);
703#****************************************************************************
704sub Parse_InfoMakeLog
705{
706 my ($strInfomake_Path, $CmplOpt_href, $RelInfo_href) = @_;
707 my $bResult = 0;
708 if(-e $strInfomake_Path)
709 {
710 open (FILE_HANDLE, $strInfomake_Path) or BuildInfo_die("Cannot open $strInfomake_Path\n", __FILE__, __LINE__);
711 while (<FILE_HANDLE>)
712 {
713 if(/^(\S+)\s*\=\s*(.*)/)
714 {
715 my $key = $1;
716 my $value = $2;
717 if($key =~ /COM_DEFS/)
718 {
719 _ParseCMPLOpt($value, $CmplOpt_href);
720 }
721 else
722 {
723 $RelInfo_href->{$1} = $2;
724 $RelInfo_href->{lc($1)} = $2;
725 }
726 }
727 }
728 close FILE_HANDLE;
729 $g_CmplOpt_href = $CmplOpt_href;
730 $g_RelInfo_href = $RelInfo_href;
731 $bResult = 1;
732 }
733 else
734 {
735 BuildInfo_die("$strInfomake_Path: NOT exist!", __FILE__, __LINE__);
736 }
737 return $bResult;
738}
739
740sub _ParseCMPLOpt
741{
742 my ($strOptions, $CmplOpt_href) = @_;
743 my @ComlOpt = split(/\s/,$strOptions);
744 foreach my $Opt(@ComlOpt)
745 {
746 $Opt =~ s/\s\n\r//;
747 next if($Opt eq "");
748 my $strkey = $Opt;
749 my $strvalue = undef;
750 if($Opt =~ /(.*)=(.*)/)
751 {
752 $strkey = $1;
753 $strvalue = $2;
754 }
755 $CmplOpt_href->{$strkey} = $strvalue;
756 $CmplOpt_href->{lc($strkey)} = $strvalue;
757 }
758}
759sub GetCmplOptRef
760{
761 my ($strInfoMake_Path) = @_;
762 if(!defined $g_CmplOpt_href)
763 {
764 my %CmplOption;
765 my %RelOption;
766 &Parse_InfoMakeLog($strInfoMake_Path, \%CmplOption, \%RelOption);
767 }
768 return $g_CmplOpt_href;
769}
770sub GetRelOptRef
771{
772 my ($strInfoMake_Path) = @_;
773 if(!defined $g_RelInfo_href)
774 {
775 my %CmplOption;
776 my %RelOption;
777 &Parse_InfoMakeLog($strInfoMake_Path, \%CmplOption, \%RelOption);
778 }
779 return $g_RelInfo_href;
780}
781#****************************************************************************
782# subroutine: exist
783# Input: $nOption: BuildOPT::CMPL or BuildOPT::REL
784# Output: In compiler option, if $strKey exists in compiler option, it will return 1,
785# otherwises returns 0
786# In release information, it's usually meaningless to see if $strKey exists
787#****************************************************************************
788sub exist
789{
790 my ($nOption, $strKey, $href) = @_;
791 if (!defined $href)
792 {
793 $href = $g_CmplOpt_href if($nOption == BuildOPT::CMPL);
794 $href = $g_RelInfo_href if($nOption == BuildOPT::REL);
795 }
796 &NoInfoMake_die($href, __FILE__, __LINE__);
797 my $bExist = 0;
798 if(exists $href->{$strKey})
799 {
800 $bExist = 1;
801 }
802 return $bExist;
803}
804
805#****************************************************************************
806# subroutine: EvaluateCompileOption
807# description: Evaluate the compile option
808# input: Compile option condition(string), compile options hash ref
809# output: 1: true, 0: false
810# need init: No
811#****************************************************************************
812sub EvaluateCompileOption
813{
814 my ($condition, $CmpOption_href) = @_;
815 $CmpOption_href = $g_CmplOpt_href if(!defined $CmpOption_href);
816 &NoInfoMake_die($CmpOption_href, __FILE__, __LINE__);
817
818 # Transform the condition to expression tree in postfix form
819 my @expressionTree;
820 _parseCompileOptionCondition($condition, \@expressionTree);
821
822 # Evaluate the expression tree
823 my @stack;
824 foreach my $token (@expressionTree)
825 {
826 if ($token eq "&&" or $token eq "||")
827 {
828 my $second = pop(@stack);
829 my $first = pop(@stack);
830 $first = exist(BuildOPT::CMPL, $first) if($first =~ /\D+/);
831 $second = exist(BuildOPT::CMPL, $second) if($second =~ /\D+/);
832 push (@stack, eval "$first $token $second");
833 }
834 elsif ($token eq "=")
835 {
836 my $second = pop(@stack);
837 my $first = pop(@stack);
838 my $value = $CmpOption_href->{$first};
839 $value = "" unless defined $value;
840 if ($value eq $second)
841 {
842 push (@stack, 1);
843 }
844 else
845 {
846 push (@stack, 0);
847 }
848 }
849 elsif ($token eq "!")
850 {
851 my $first = pop(@stack);
852 $first = exist(BuildOPT::CMPL, $first) if($first =~ /\D+/);
853 if ($first == 1)
854 {
855 push (@stack, 0);
856 }
857 else
858 {
859 push (@stack, 1);
860 }
861 }
862 else
863 {
864 push @stack, $token;
865 }
866 }
867
868 &BuildInfo_die("Incorrect syntax of compile option condition \"$condition\"", __FILE__, __LINE__)
869 unless (1 == @stack);
870 # for single compile option
871 my $ZeroString = "0"; $ZeroString = sprintf("%d", $ZeroString); # convert
872 my $OneString = "1"; $OneString = sprintf("%d", $OneString); # convert
873 $stack[0] = (exist(BuildOPT::CMPL, $stack[0])?1:0) if($ZeroString ne $stack[0] && $OneString ne $stack[0]) ;
874
875 #use above safer syntax
876 #$stack[0] = (exist(BuildOPT::CMPL, $stack[0])?1:0) if("0" ne $stack[0] && "1" ne $stack[0]) ;
877
878 return $stack[0];
879
880}
881#****************************************************************************
882# subroutine: _parseCompileOptionCondition
883# description: Parse the feature option condition to postfix form.
884# input: Feature option condition, expression tree ref
885# output: Expression tree
886# need init: No
887#****************************************************************************
888sub _parseCompileOptionCondition
889{
890 my ($condition, $expressionTreeRef) = @_;
891 my $conditionNoSpace = $condition;
892 $conditionNoSpace =~ s/ //g;
893
894 my @tokens = split(/(=|\(|\)|&&|\|\||!)/, $conditionNoSpace);
895 my @stack;
896
897 # For error checking
898 my $parenthesis = 0;
899 my $operand = 0;
900 my $operator = 0;
901
902 foreach my $token (@tokens)
903 {
904 if ($token eq "")
905 {
906 # Skip empty token
907 next;
908 }
909 elsif ($token eq "(")
910 {
911 push @stack, $token;
912 ++$parenthesis;
913 }
914 elsif ($token eq ")")
915 {
916 &BuildInfo_die("Incorrect syntax of compile option condition \"$condition\"", __FILE__, __LINE__)
917 unless (0 < $parenthesis);
918 my $temp = pop(@stack);
919
920 while ($temp ne "(")
921 {
922 push @$expressionTreeRef, $temp;
923 $temp = pop(@stack);
924 }
925
926 --$parenthesis;
927 }
928 elsif ($token eq "=" or $token eq "&&" or $token eq "||" or $token eq "!")
929 {
930 my $needLoop = 0;
931
932 do
933 {
934 if (0 == scalar(@stack) or $stack[-1] eq "(")
935 {
936 # Stack is empty or stack top eqals to (
937 push @stack, $token;
938 $needLoop = 0;
939 }
940 elsif (0 < _compareCompileOptionOperator($stack[-1], $token))
941 {
942 # Stack top has higher priority than current token
943 push @stack, $token;
944 $needLoop = 0;
945 }
946 else
947 {
948 push @$expressionTreeRef, pop(@stack);
949 $needLoop = 1;
950 }
951 } while ($needLoop);
952
953 $operator += 1 unless ($token eq "!");
954 }
955 elsif ($token =~ /\w+/)
956 {
957 # Operand
958 push @$expressionTreeRef, $token;
959 $operand += 1;
960 }
961 else
962 {
963 &BuildInfo_die("Incorrect syntax of compile option condition \"$condition\"", __FILE__, __LINE__);
964 }
965 }
966
967 &BuildInfo_die("Incorrect syntax of compile option condition \"$condition\"", __FILE__, __LINE__)
968 unless ($operator == ($operand - 1) and 0 == $parenthesis);
969
970 push @$expressionTreeRef, reverse(@stack);
971}
972
973sub _compareCompileOptionOperator
974{
975 my $first = shift;
976 my $second = shift;
977 my %operatorToNumber = ("=" => 0, "!" => 1, "&&" => 2, "||" => 2);
978
979 return $operatorToNumber{$first} <=> $operatorToNumber{$second};
980}
981
982#****************************************************************************
983# subroutine: get
984# Input: $nOption: BuildOPT::CMPL or BuildOPT::REL
985# Output: In compiler option, if it's ooo=xxx, it returns xxx
986# otherwises, it returns undef
987# In release information, it returns value directly
988#****************************************************************************
989sub get
990{
991 my ($nOption, $strKey, $href) = @_;
992 if (!defined $href)
993 {
994 $href = $g_CmplOpt_href if($nOption == BuildOPT::CMPL);
995 $href = $g_RelInfo_href if($nOption == BuildOPT::REL);
996 }
997 &NoInfoMake_die($href, __FILE__, __LINE__);
998 my $strValue = undef;
999 if(exists $href->{$strKey})
1000 {
1001 $strValue = $href->{$strKey};
1002 }
1003 return $strValue;
1004}
1005#****************************************************************************
1006# subroutine: is
1007# Input: $nOption: BuildOPT::CMPL or BuildOPT::REL
1008# Output: 1=$href->{$strKey} equals to $strValue, 0=not equal
1009#****************************************************************************
1010sub is
1011{
1012 my ($nOption, $strKey, $strValue, $href) = @_;
1013 if (!defined $href)
1014 {
1015 $href = $g_CmplOpt_href if($nOption == BuildOPT::CMPL);
1016 $href = $g_RelInfo_href if($nOption == BuildOPT::REL);
1017 }
1018 &NoInfoMake_die($href, __FILE__, __LINE__);
1019 my $bResult = 0;
1020 if(exists $href->{$strKey})
1021 {
1022 $bResult =1 if(lc($strValue) eq lc($href->{$strKey}));
1023 }
1024 return $bResult;
1025}
1026#****************************************************************************
1027# subroutine: BuildInfo_die
1028# sample code: (message, __FILE__, __LINE__)
1029# input: $error_msg, $file, $line_no
1030#****************************************************************************
1031sub BuildInfo_die
1032{
1033 my ($error_msg, $file, $line_no) = @_;
1034 &sysUtil::error_handler($error_msg, $file, $line_no, 'BuildInfoParser');
1035}
1036
1037sub NoInfoMake_die
1038{
1039 my ($temp_ref, $file, $line_no) = @_;
1040 &BuildInfo_die("Please parse infomake.log by BuildInfo::ParseInfoMakeLog() before using it.", $file, $line_no)
1041 if(!defined $temp_ref);
1042}