blob: 4e798b8c7a89ea90b2cadafd81d350b5158167eb [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) 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#!/usr/bin/perl
37# filter out the lines having no define options
38
39
40#
41# parsing command arguments
42#
43my $line_no;
44my $debug_print = 0; # 1 for debug; 0 for non-debug
45
46if (!($ARGV[0] =~ /\.(h|c|hpp|cpp|s|java|inc)$/i))
47{
48 &usage;
49}
50if (!(($ARGV[1] =~ /info\.log$/i) || ($ARGV[1] =~ /\.def$/i)) || !($ARGV[2] =~ /\.def$/i))
51{
52 &usage;
53}
54if (!($ARGV[3] =~ /\.(h|c|hpp|cpp|s|java|inc)$/i))
55{
56 &usage;
57}
58
59#
60#get %opt_list
61#
62my %opt_list;
63my $ENOPT_FILE = $ARGV[1];
64open ENOPT_FILE, "<$ENOPT_FILE" or die "cannot open $ENOPT_FILE\n";
65
66my $is_option_area = -1; # -1: not in a option area
67 # 1: in a option area
68my $log_turnon = "[ COMMON OPTION ]";
69my $log_turnoff = "[ COMMON INCLUDE PATH ]";
70my $opt_no = 0;
71while (<ENOPT_FILE>)
72{
73 $read_line = $_;
74
75 if ((index($read_line, $log_turnon) >=0) && ($is_option_area == -1))
76 {
77 $is_option_area = 1;
78 }
79 elsif ((index($read_line, $log_turnoff) >=0) && ($is_option_area == 1))
80 {
81 $is_option_area = -1;
82 }
83 else
84 {
85 if ($is_option_area == 1)
86 {
87 $read_line =~ s/\s*(\w+)\s*(\n)+/$1/;
88 $opt_list{$read_line} = 1;
89 $opt_no ++;
90 }
91 }
92}
93close ENOPT_FILE;
94#print $opt_no;
95#exit(0);
96
97my $DISOPT_FILE = $ARGV[2];
98open DISOPT_FILE, "<$DISOPT_FILE" or die "cannot open $DISOPT_FILE\n";
99while (<DISOPT_FILE>)
100{
101 s/\s*(\w+)\s*(\n)+/$1/;
102 $opt_list{$_} = 0;
103}
104close DISOPT_FILE;
105
106#
107# open source file & result file
108#
109my $SRC_FILE = $ARGV[0];
110my $is_exist = 0;
111$is_exist = 1 if -e $SRC_FILE;
112if ($is_exist == 1)
113{
114 open SRC_FILE, "<$SRC_FILE" or die "cannot open $SRC_FILE\n";
115}
116else
117{
118 print "$SRC_FILE is not existed!!!\n";
119 exit(1);
120}
121
122my $RSLT_FILE = $ARGV[3];
123open RSLT_FILE, ">$RSLT_FILE" or die "cannot open $RSLT_FILE\n";
124
125#
126# record lines in multi-line comments in %in_mline_cmt_list
127# !!!nested comments are not applicable
128#
129# %in_mline_cmt_list is used to record the line which is in a multi-line comment
130# $key : line number in a multi-line comment
131# $value 0: the beginning line of the multi-line comment
132# 1: the line between the beginning and the end lines of the multi-line comment
133# 2: the end line of the multi-line comment
134# 3: the end line of one multi-line comment & the beginning line of another multi-line comment
135my $is_in_mline_cmt = 0;
136$line_no = 1;
137#print "scanning comment\n";
138while (<SRC_FILE>)
139{
140 my $line = $_;
141 my $cmt_ptn;
142
143 if ($is_in_mline_cmt == 1)
144 {
145 if ($line =~ /\*\//)
146 {
147 $in_mline_cmt_list{$line_no} = 2;
148 $is_in_mline_cmt = 0;
149 $line =~ s{.*?\*/}{};
150 }
151 else
152 {
153 $in_mline_cmt_list{$line_no} = 1;
154 }
155# print $in_mline_cmt_list{$line_no};
156 }
157 else
158 {
159# print "-";
160 }
161
162 while ( $line =~ /\/\/|\/\*/ )
163 {
164 $cmt_ptn = $&;
165
166 if ( $line =~ /\".*?(\/\/|\/\*).*?\"/ )
167 {
168 last;
169 }
170# print "$line \t $cmt_ptn \n";
171
172 if ($cmt_ptn =~ /\/\//)
173 {
174 $line =~ s{//.*}{\n};
175 }
176 elsif ($cmt_ptn =~ /\/\*/)
177 {
178 $line =~ /\/\*/;
179 if ($' =~ /\*\//)#'
180 {
181 $line =~ s{/\*.*?\*/}{};
182 }
183 else
184 {
185 $in_mline_cmt_list{$line_no} = ( exists $in_mline_cmt_list{$line_no} )? 3 : 0;
186 $is_in_mline_cmt = 1;
187# print $in_mline_cmt_list{$line_no};
188 last;
189 }
190 }
191 }
192 $line_no ++;
193 if (($line =~ /\\$/) || ($line =~ /\\\r/))
194 {
195 $in_mline_cmt_list{$line_no} = 4;
196 }
197# print "$line_no \n";
198} # foreach (<SRC_FILE>) of record lines in multi-line comments in %in_mline_cmt_list
199seek(SRC_FILE, 0, 0);
200
201
202#print "start parsing...\n";
203#
204# parsing directives: #if, #ifdef, #ifndef, #endif, #else, #elif
205#
206$line_no = 1;
207while (<SRC_FILE>)
208{
209 $read_line = $_;
210
211 print "$line_no\t" if ($debug_print == 1);
212 if (((/^\s*\#\s*if/) || (/^\s*\/\*.*\*\/\s*\#\s*if/) || (/^\s*\#\s*if/)) && !($in_mline_cmt_list{$line_no} > 0))
213 {
214 print RSLT_FILE $read_line;
215 # remove the comment in expression first
216 $uncommented_line = &rm_cmt($read_line);
217 while ($uncommented_line eq 'A non-ended multiple-line comment!!!')
218 {
219 chomp($read_line);
220 print "$uncommented_line\n" if ($debug_print == 1);
221 $read_line =~ s/\\$//;
222 $read_line =~ s/\\\r//;
223 $extra_line = <SRC_FILE>;
224 $line_no ++;
225 print "$line_no\t" if ($debug_print == 1);
226 print RSLT_FILE $extra_line;
227 $read_line .= $extra_line;
228 $uncommented_line = &rm_cmt($read_line);
229 }
230 &do_ifxxx($uncommented_line);
231 }
232 elsif (((/^\s*\#\s*endif/) || (/^\s*\/\*.*\*\/\s*\#\s*endif/)) && !($in_mline_cmt_list{$line_no} > 0))
233 {
234 print RSLT_FILE $read_line;
235 &do_endif;
236 }
237 elsif (((/^\s*\#\s*else/) || (/^\s*\/\*.*\*\/\s*\#\s*else/)) && !($in_mline_cmt_list{$line_no} > 0))
238 {
239 print RSLT_FILE $read_line;
240 &do_else;
241 }
242 elsif (((/^\s*\#\s*elif/) || (/^\s*\/\*.*\*\/\s*\#\s*elif/)) && !($in_mline_cmt_list{$line_no} > 0))
243 {
244 print RSLT_FILE $read_line;
245 # remove the comment in expression first
246 $uncommented_line = &rm_cmt($read_line);
247 while ($uncommented_line eq 'A non-ended multiple-line comment!!!')
248 {
249 chomp($read_line);
250 print "$uncommented_line\n" if ($debug_print == 1);
251 $read_line =~ s/\\$//;
252 $read_line =~ s/\\\r//;
253 $extra_line = <SRC_FILE>;
254 $line_no ++;
255 print "$line_no\t" if ($debug_print == 1);
256 print RSLT_FILE $extra_line;
257 $read_line .= $extra_line;
258 $uncommented_line = &rm_cmt($read_line);
259 }
260 &do_elif($uncommented_line);
261 }
262 else
263 {
264 if (@if_stack != ())
265 {
266 my $need_prn;
267 my $need_removal = 0;
268
269 for ($i=$#if_stack; $i>=0; $i--)
270 {
271 $if_truth_value_list = $if_stack[$i];
272 $if_truth_value_list =~ m/(\w)\s*$/;
273 $need_prn = $1;
274 print "<$need_prn>" if ($debug_print == 1);
275 if ($need_prn =~ /0/)
276 {
277 $need_removal = 1;
278 last;
279 }
280 }
281 print "\n" if ($debug_print == 1);
282
283 ($need_removal == 1) ?
284 print RSLT_FILE "/* under construction !*/\n" :
285 print RSLT_FILE $read_line;
286 }
287 else
288 {
289 print RSLT_FILE $read_line;
290 print "1\n" if ($debug_print == 1);
291 }
292 }
293 $line_no ++;
294} # foreach (<SRC_FILE>) of parsing directives: #if, #ifdef, #ifndef, #endif, #else, #elif
295
296close SRC_FILE;
297close RSLT_FILE;
298
299exit 0;
300
301# show usage
302sub usage
303{
304 print "USAGE: perl if_fil.pl <source file> <enabled define options> <disabled define options> <destination file>\n";
305 exit(0);
306}
307
308# remove comment in line
309sub rm_cmt
310{
311 my $line;
312 my $cmt_ptn;
313
314 $_ = $_[0];
315 while (/\/\/|\/\*/)
316 {
317 $line = $_;
318 $cmt_ptn = $&;
319 if ($cmt_ptn =~ /\/\//)
320 {
321 $line =~ s{//.*\n}{\n};
322 }
323 elsif ($cmt_ptn =~ /\/\*/)
324 { # nested comments are not applicable!!!
325 if ($line =~ /\*\//)
326 {
327 $line =~ s{/\*.*?\*/}{};
328 }
329 else
330 {
331 return "A non-ended multiple-line comment!!!";
332 }
333 }
334 $_ = $line;
335 }
336 if ((/\\$/) || (/\\\r/))
337 {
338 return "A non-ended multiple-line comment!!!";
339 }
340 return $_;
341}
342
343# determine the truth value of a conditional expression
344sub truth_exp
345{
346 my $line;
347 my $opt;
348 my $opt_value;
349 my $exp_rslt;
350 my $undetermin_cnt = 0;
351 my $determin_cnt = 0;
352 $_ = $_[0];
353
354 s/defined//g;
355 if (/'\\?(.|\w+)'/)
356 {
357 # workaround for #if 'A' == '\301' in applib\sqlite3\inc\sqliteInt.h
358 return "_ ";
359 }
360 s/\b[A-Za-z_]\w*\s*(<=|==|>=|!=|<|>)\s*\d+\b/_/g;
361 if ((/\b0\s*\&\&/) || (/\&\&\s*0\b/) || (/\b1\s*\|\|/) || (/\|\|\s*1\b/))
362 {
363 $determin_cnt = 1;
364 }
365 while (/\b([A-Za-z_]\w*)\b/)
366 {
367 $line = $_;
368 $opt = $1;
369 if ( exists $opt_list{$opt})
370 {
371 $determin_cnt++;
372 $opt_value = $opt_list{$opt};
373 $line =~ s/$opt/$opt_value/;
374 }
375 else
376 {
377 $undetermin_cnt ++;
378 $line =~ s/$opt/\#/;
379 #print "[$line]";
380 }
381 $_ = $line;
382 }
383 s/!/int!/g;
384 #print "[$undetermin_cnt]";
385 $line = $_;
386 if ($undetermin_cnt == 0)
387 {
388 $exp_rslt = eval($line);
389 }
390 elsif ($determin_cnt == 0)
391 {
392 return "_ ";
393 }
394 elsif (($undetermin_cnt > 22) && ($line =~ /\b(0|1)\b/))
395 {
396 return "_ ";
397 }
398 else # if ($undetermin_cnt > 0)
399 {
400 my $pre_exp_rslt = -1;
401 my $index;
402 for ($index=0; $index<2**$undetermin_cnt; $index++)
403 {
404 #print "\n$_ = ";
405 my $i = $index;
406 my $ln = $line;
407 foreach (1..$undetermin_cnt)
408 {
409 my $mod = $i % 2;
410 $ln =~ s/\#/$mod/;
411 $i -= $mod;
412 $i /= 2;
413 }
414
415 $exp_rslt = eval($ln);
416 #print "[$exp_rslt]";
417 if ($pre_exp_rslt == -1)
418 {
419 $pre_exp_rslt = $exp_rslt;
420 }
421 else
422 {
423 if ($pre_exp_rslt != $exp_rslt)
424 {
425 $exp_rslt = "";
426 last;
427 }
428 }
429 } # foreach (0..2**$undetermin_cnt-1)
430 }
431 if ($exp_rslt =~ /1/)
432 {
433 # print "$line ==> $exp_rslt";
434 return "1 ";
435 }
436 elsif ($exp_rslt =~ /0/)
437 {
438 # print "$line ==> $exp_rslt";
439 return "0 ";
440 }
441 else
442 {
443 return "_ ";
444 }
445}
446
447# do for #ifndef, #ifdef, #if
448sub do_ifxxx
449{
450 my $truth_value;
451
452 # determine current expression truth value
453 $_ = $_[0];
454 if ( (s/^\s*\#\s*ifndef\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*ifndef\s+(.+)\n$/$1/))
455 {
456 s/\s+/ /g;
457 s/\s+$//;
458 $opt = $_;
459 if ( exists $opt_list{$opt} )
460 {
461 if ($opt_list{$opt} == 0) # is in the $dis_opt_list
462 {
463 $truth_value = "1 ";
464 }
465 elsif ($opt_list{$opt} == 1) # is in the $en_opt_list
466 {
467 $truth_value = "0 ";
468 }
469 }
470 else # $opt is in neither $en_opt_list nor $dis_opt_list
471 {
472 $truth_value = "_ ";
473 }
474 print "#ifndef $opt ==> $truth_value\n" if ($debug_print == 1);
475 }
476 elsif ( (s/^\s*\#\s*ifdef\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*ifdef\s+(.+)\n$/$1/))
477 {
478 s/\s+/ /g;
479 s/\s+$//;
480 $opt = $_;
481 if ( exists $opt_list{$opt} )
482 {
483 if ($opt_list{$opt} == 0) # is in the $dis_opt_list
484 {
485 $truth_value = "0 ";
486 }
487 elsif ($opt_list{$opt} == 1) # is in the $en_opt_list
488 {
489 $truth_value = "1 ";
490 }
491 }
492 else # $opt is in neither $en_opt_list nor $dis_opt_list
493 {
494 $truth_value = "_ ";
495 }
496 print "#ifdef $opt ==> $truth_value\n" if ($debug_print == 1);
497 }
498 elsif ( (s/^\s*\#\s*if\s+(.+)\n$/$1/) || (s/^\s*\/\*.*\*\/\s*\#\s*if\s+(.+)\n$/$1/))
499 {
500 $truth_value = &truth_exp($_);
501 print "#if $_ ==> $truth_value\n" if ($debug_print == 1);
502 }
503
504 # push an entry into @if_stack
505 push @if_stack, $truth_value;
506}
507
508# do for #endif
509sub do_endif
510{
511 pop @if_stack;
512 print "#endif\n" if ($debug_print == 1);
513}
514
515# do for #else
516sub do_else
517{
518 $if_stack[-1] .= ($if_stack[-1] =~ /1/) ? "0 " : "1 ";
519
520 # Just fur debug
521 $_ = $if_stack[-1];
522 m/(\d)\s*$/;
523 print "#else ==> $1\n" if ($debug_print == 1);
524}
525
526# do for #elif
527sub do_elif
528{
529 my $truth_value;
530
531 $_ = $_[0];
532 s/^\s*\#\s*elif\s+(.+)\n$/$1/;
533 $truth_value = &truth_exp($_);
534 $if_stack[-1] .= $truth_value;
535 print "#elif $if_stack[-1]\n" if ($debug_print == 1);
536}