#!/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). | |
# | |
# | |
#!/usr/bin/perl | |
# filter out the lines having no define options | |
# | |
# parsing command arguments | |
# | |
my $line_no; | |
my $debug_print = 0; # 1 for debug; 0 for non-debug | |
if (!($ARGV[0] =~ /\.(h|c|hpp|cpp|s|java|inc)$/i)) | |
{ | |
&usage; | |
} | |
if (!(($ARGV[1] =~ /info\.log$/i) || ($ARGV[1] =~ /\.def$/i)) || !($ARGV[2] =~ /\.def$/i)) | |
{ | |
&usage; | |
} | |
if (!($ARGV[3] =~ /\.(h|c|hpp|cpp|s|java|inc)$/i)) | |
{ | |
&usage; | |
} | |
# | |
#get %opt_list | |
# | |
my %opt_list; | |
my $ENOPT_FILE = $ARGV[1]; | |
open ENOPT_FILE, "<$ENOPT_FILE" or die "cannot open $ENOPT_FILE\n"; | |
my $is_option_area = -1; # -1: not in a option area | |
# 1: in a option area | |
my $log_turnon = "[ COMMON OPTION ]"; | |
my $log_turnoff = "[ COMMON INCLUDE PATH ]"; | |
my $opt_no = 0; | |
while (<ENOPT_FILE>) | |
{ | |
$read_line = $_; | |
if ((index($read_line, $log_turnon) >=0) && ($is_option_area == -1)) | |
{ | |
$is_option_area = 1; | |
} | |
elsif ((index($read_line, $log_turnoff) >=0) && ($is_option_area == 1)) | |
{ | |
$is_option_area = -1; | |
} | |
else | |
{ | |
if ($is_option_area == 1) | |
{ | |
$read_line =~ s/\s*(\w+)\s*(\n)+/$1/; | |
$opt_list{$read_line} = 1; | |
$opt_no ++; | |
} | |
} | |
} | |
close ENOPT_FILE; | |
#print $opt_no; | |
#exit(0); | |
my $DISOPT_FILE = $ARGV[2]; | |
open DISOPT_FILE, "<$DISOPT_FILE" or die "cannot open $DISOPT_FILE\n"; | |
while (<DISOPT_FILE>) | |
{ | |
s/\s*(\w+)\s*(\n)+/$1/; | |
$opt_list{$_} = 0; | |
} | |
close DISOPT_FILE; | |
# | |
# open source file & result file | |
# | |
my $SRC_FILE = $ARGV[0]; | |
my $is_exist = 0; | |
$is_exist = 1 if -e $SRC_FILE; | |
if ($is_exist == 1) | |
{ | |
open SRC_FILE, "<$SRC_FILE" or die "cannot open $SRC_FILE\n"; | |
} | |
else | |
{ | |
print "$SRC_FILE is not existed!!!\n"; | |
exit(1); | |
} | |
my $RSLT_FILE = $ARGV[3]; | |
open RSLT_FILE, ">$RSLT_FILE" or die "cannot open $RSLT_FILE\n"; | |
# | |
# record lines in multi-line comments in %in_mline_cmt_list | |
# !!!nested comments are not applicable | |
# | |
# %in_mline_cmt_list is used to record the line which is in a multi-line comment | |
# $key : line number in a multi-line comment | |
# $value 0: the beginning line of the multi-line comment | |
# 1: the line between the beginning and the end lines of the multi-line comment | |
# 2: the end line of the multi-line comment | |
# 3: the end line of one multi-line comment & the beginning line of another multi-line comment | |
my $is_in_mline_cmt = 0; | |
$line_no = 1; | |
#print "scanning comment\n"; | |
while (<SRC_FILE>) | |
{ | |
my $line = $_; | |
my $cmt_ptn; | |
if ($is_in_mline_cmt == 1) | |
{ | |
if ($line =~ /\*\//) | |
{ | |
$in_mline_cmt_list{$line_no} = 2; | |
$is_in_mline_cmt = 0; | |
$line =~ s{.*?\*/}{}; | |
} | |
else | |
{ | |
$in_mline_cmt_list{$line_no} = 1; | |
} | |
# print $in_mline_cmt_list{$line_no}; | |
} | |
else | |
{ | |
# print "-"; | |
} | |
while ( $line =~ /\/\/|\/\*/ ) | |
{ | |
$cmt_ptn = $&; | |
if ( $line =~ /\".*?(\/\/|\/\*).*?\"/ ) | |
{ | |
last; | |
} | |
# print "$line \t $cmt_ptn \n"; | |
if ($cmt_ptn =~ /\/\//) | |
{ | |
$line =~ s{//.*}{\n}; | |
} | |
elsif ($cmt_ptn =~ /\/\*/) | |
{ | |
$line =~ /\/\*/; | |
if ($' =~ /\*\//)#' | |
{ | |
$line =~ s{/\*.*?\*/}{}; | |
} | |
else | |
{ | |
$in_mline_cmt_list{$line_no} = ( exists $in_mline_cmt_list{$line_no} )? 3 : 0; | |
$is_in_mline_cmt = 1; | |
# print $in_mline_cmt_list{$line_no}; | |
last; | |
} | |
} | |
} | |
$line_no ++; | |
if (($line =~ /\\$/) || ($line =~ /\\\r/)) | |
{ | |
$in_mline_cmt_list{$line_no} = 4; | |
} | |
# print "$line_no \n"; | |
} # foreach (<SRC_FILE>) of record lines in multi-line comments in %in_mline_cmt_list | |
seek(SRC_FILE, 0, 0); | |
#print "start parsing...\n"; | |
# | |
# parsing directives: #if, #ifdef, #ifndef, #endif, #else, #elif | |
# | |
$line_no = 1; | |
while (<SRC_FILE>) | |
{ | |
$read_line = $_; | |
print "$line_no\t" if ($debug_print == 1); | |
if (((/^\s*\#\s*if/) || (/^\s*\/\*.*\*\/\s*\#\s*if/) || (/^\s*\#\s*if/)) && !($in_mline_cmt_list{$line_no} > 0)) | |
{ | |
print RSLT_FILE $read_line; | |
# remove the comment in expression first | |
$uncommented_line = &rm_cmt($read_line); | |
while ($uncommented_line eq 'A non-ended multiple-line comment!!!') | |
{ | |
chomp($read_line); | |
print "$uncommented_line\n" if ($debug_print == 1); | |
$read_line =~ s/\\$//; | |
$read_line =~ s/\\\r//; | |
$extra_line = <SRC_FILE>; | |
$line_no ++; | |
print "$line_no\t" if ($debug_print == 1); | |
print RSLT_FILE $extra_line; | |
$read_line .= $extra_line; | |
$uncommented_line = &rm_cmt($read_line); | |
} | |
&do_ifxxx($uncommented_line); | |
} | |
elsif (((/^\s*\#\s*endif/) || (/^\s*\/\*.*\*\/\s*\#\s*endif/)) && !($in_mline_cmt_list{$line_no} > 0)) | |
{ | |
print RSLT_FILE $read_line; | |
&do_endif; | |
} | |
elsif (((/^\s*\#\s*else/) || (/^\s*\/\*.*\*\/\s*\#\s*else/)) && !($in_mline_cmt_list{$line_no} > 0)) | |
{ | |
print RSLT_FILE $read_line; | |
&do_else; | |
} | |
elsif (((/^\s*\#\s*elif/) || (/^\s*\/\*.*\*\/\s*\#\s*elif/)) && !($in_mline_cmt_list{$line_no} > 0)) | |
{ | |
print RSLT_FILE $read_line; | |
# remove the comment in expression first | |
$uncommented_line = &rm_cmt($read_line); | |
while ($uncommented_line eq 'A non-ended multiple-line comment!!!') | |
{ | |
chomp($read_line); | |
print "$uncommented_line\n" if ($debug_print == 1); | |
$read_line =~ s/\\$//; | |
$read_line =~ s/\\\r//; | |
$extra_line = <SRC_FILE>; | |
$line_no ++; | |
print "$line_no\t" if ($debug_print == 1); | |
print RSLT_FILE $extra_line; | |
$read_line .= $extra_line; | |
$uncommented_line = &rm_cmt($read_line); | |
} | |
&do_elif($uncommented_line); | |
} | |
else | |
{ | |
if (@if_stack != ()) | |
{ | |
my $need_prn; | |
my $need_removal = 0; | |
for ($i=$#if_stack; $i>=0; $i--) | |
{ | |
$if_truth_value_list = $if_stack[$i]; | |
$if_truth_value_list =~ m/(\w)\s*$/; | |
$need_prn = $1; | |
print "<$need_prn>" if ($debug_print == 1); | |
if ($need_prn =~ /0/) | |
{ | |
$need_removal = 1; | |
last; | |
} | |
} | |
print "\n" if ($debug_print == 1); | |
($need_removal == 1) ? | |
print RSLT_FILE "/* under construction !*/\n" : | |
print RSLT_FILE $read_line; | |
} | |
else | |
{ | |
print RSLT_FILE $read_line; | |
print "1\n" if ($debug_print == 1); | |
} | |
} | |
$line_no ++; | |
} # foreach (<SRC_FILE>) of parsing directives: #if, #ifdef, #ifndef, #endif, #else, #elif | |
close SRC_FILE; | |
close RSLT_FILE; | |
exit 0; | |
# show usage | |
sub usage | |
{ | |
print "USAGE: perl if_fil.pl <source file> <enabled define options> <disabled define options> <destination file>\n"; | |
exit(0); | |
} | |
# remove comment in line | |
sub rm_cmt | |
{ | |
my $line; | |
my $cmt_ptn; | |
$_ = $_[0]; | |
while (/\/\/|\/\*/) | |
{ | |
$line = $_; | |
$cmt_ptn = $&; | |
if ($cmt_ptn =~ /\/\//) | |
{ | |
$line =~ s{//.*\n}{\n}; | |
} | |
elsif ($cmt_ptn =~ /\/\*/) | |
{ # nested comments are not applicable!!! | |
if ($line =~ /\*\//) | |
{ | |
$line =~ s{/\*.*?\*/}{}; | |
} | |
else | |
{ | |
return "A non-ended multiple-line comment!!!"; | |
} | |
} | |
$_ = $line; | |
} | |
if ((/\\$/) || (/\\\r/)) | |
{ | |
return "A non-ended multiple-line comment!!!"; | |
} | |
return $_; | |
} | |
# determine the truth value of a conditional expression | |
sub truth_exp | |
{ | |
my $line; | |
my $opt; | |
my $opt_value; | |
my $exp_rslt; | |
my $undetermin_cnt = 0; | |
my $determin_cnt = 0; | |
$_ = $_[0]; | |
s/defined//g; | |
if (/'\\?(.|\w+)'/) | |
{ | |
# workaround for #if 'A' == '\301' in applib\sqlite3\inc\sqliteInt.h | |
return "_ "; | |
} | |
s/\b[A-Za-z_]\w*\s*(<=|==|>=|!=|<|>)\s*\d+\b/_/g; | |
if ((/\b0\s*\&\&/) || (/\&\&\s*0\b/) || (/\b1\s*\|\|/) || (/\|\|\s*1\b/)) | |
{ | |
$determin_cnt = 1; | |
} | |
while (/\b([A-Za-z_]\w*)\b/) | |
{ | |
$line = $_; | |
$opt = $1; | |
if ( exists $opt_list{$opt}) | |
{ | |
$determin_cnt++; | |
$opt_value = $opt_list{$opt}; | |
$line =~ s/$opt/$opt_value/; | |
} | |
else | |
{ | |
$undetermin_cnt ++; | |
$line =~ s/$opt/\#/; | |
#print "[$line]"; | |
} | |
$_ = $line; | |
} | |
s/!/int!/g; | |
#print "[$undetermin_cnt]"; | |
$line = $_; | |
if ($undetermin_cnt == 0) | |
{ | |
$exp_rslt = eval($line); | |
} | |
elsif ($determin_cnt == 0) | |
{ | |
return "_ "; | |
} | |
elsif (($undetermin_cnt > 22) && ($line =~ /\b(0|1)\b/)) | |
{ | |
return "_ "; | |
} | |
else # if ($undetermin_cnt > 0) | |
{ | |
my $pre_exp_rslt = -1; | |
my $index; | |
for ($index=0; $index<2**$undetermin_cnt; $index++) | |
{ | |
#print "\n$_ = "; | |
my $i = $index; | |
my $ln = $line; | |
foreach (1..$undetermin_cnt) | |
{ | |
my $mod = $i % 2; | |
$ln =~ s/\#/$mod/; | |
$i -= $mod; | |
$i /= 2; | |
} | |
$exp_rslt = eval($ln); | |
#print "[$exp_rslt]"; | |
if ($pre_exp_rslt == -1) | |
{ | |
$pre_exp_rslt = $exp_rslt; | |
} | |
else | |
{ | |
if ($pre_exp_rslt != $exp_rslt) | |
{ | |
$exp_rslt = ""; | |
last; | |
} | |
} | |
} # foreach (0..2**$undetermin_cnt-1) | |
} | |
if ($exp_rslt =~ /1/) | |
{ | |
# print "$line ==> $exp_rslt"; | |
return "1 "; | |
} | |
elsif ($exp_rslt =~ /0/) | |
{ | |
# print "$line ==> $exp_rslt"; | |
return "0 "; | |
} | |
else | |
{ | |
return "_ "; | |
} | |
} | |
# do for #ifndef, #ifdef, #if | |
sub do_ifxxx | |
{ | |
my $truth_value; | |
# determine current expression truth value | |
$_ = $_[0]; | |
if ( (s/^\s*\#\s*ifndef\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*ifndef\s+(.+)\n$/$1/)) | |
{ | |
s/\s+/ /g; | |
s/\s+$//; | |
$opt = $_; | |
if ( exists $opt_list{$opt} ) | |
{ | |
if ($opt_list{$opt} == 0) # is in the $dis_opt_list | |
{ | |
$truth_value = "1 "; | |
} | |
elsif ($opt_list{$opt} == 1) # is in the $en_opt_list | |
{ | |
$truth_value = "0 "; | |
} | |
} | |
else # $opt is in neither $en_opt_list nor $dis_opt_list | |
{ | |
$truth_value = "_ "; | |
} | |
print "#ifndef $opt ==> $truth_value\n" if ($debug_print == 1); | |
} | |
elsif ( (s/^\s*\#\s*ifdef\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*ifdef\s+(.+)\n$/$1/)) | |
{ | |
s/\s+/ /g; | |
s/\s+$//; | |
$opt = $_; | |
if ( exists $opt_list{$opt} ) | |
{ | |
if ($opt_list{$opt} == 0) # is in the $dis_opt_list | |
{ | |
$truth_value = "0 "; | |
} | |
elsif ($opt_list{$opt} == 1) # is in the $en_opt_list | |
{ | |
$truth_value = "1 "; | |
} | |
} | |
else # $opt is in neither $en_opt_list nor $dis_opt_list | |
{ | |
$truth_value = "_ "; | |
} | |
print "#ifdef $opt ==> $truth_value\n" if ($debug_print == 1); | |
} | |
elsif ( (s/^\s*\#\s*if\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*if\s+(.+)\n$/$1/)) | |
{ | |
$truth_value = &truth_exp($_); | |
print "#if $_ ==> $truth_value\n" if ($debug_print == 1); | |
} | |
# push an entry into @if_stack | |
push @if_stack, $truth_value; | |
} | |
# do for #endif | |
sub do_endif | |
{ | |
pop @if_stack; | |
print "#endif\n" if ($debug_print == 1); | |
} | |
# do for #else | |
sub do_else | |
{ | |
$if_stack[-1] .= ($if_stack[-1] =~ /1/) ? "0 " : "1 "; | |
# Just fur debug | |
$_ = $if_stack[-1]; | |
m/(\d)\s*$/; | |
print "#else ==> $1\n" if ($debug_print == 1); | |
} | |
# do for #elif | |
sub do_elif | |
{ | |
my $truth_value; | |
$_ = $_[0]; | |
s/^\s*\#\s*elif\s+(.+)\n$/$1/; | |
$truth_value = &truth_exp($_); | |
$if_stack[-1] .= $truth_value; | |
print "#elif $if_stack[-1]\n" if ($debug_print == 1); | |
} |