imgtools/buildrom/tools/featureconfigurator.pl
changeset 697 818fe0ed324b
equal deleted inserted replaced
696:30aa553e9465 697:818fe0ed324b
       
     1 #
       
     2 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 # This package is to build rom image
       
    16 #
       
    17 
       
    18 use FindBin;		# for FindBin::Bin
       
    19 my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
       
    20 my $PerlEPOCPath;
       
    21 
       
    22 BEGIN {
       
    23 # check user has a version of perl that will cope
       
    24 	require 5.005_03;
       
    25 # establish the path to the Perl libraries
       
    26     $PerlLibPath = $FindBin::Bin;	
       
    27 #    $PerlLibPath =~ s/\//\\/g;
       
    28     $PerlLibPath .= "\\";
       
    29     $PerlLibPath =~ s/\\/\//g;
       
    30     
       
    31     $PerlEPOCPath = $ENV{EPOCROOT};
       
    32     $PerlEPOCPath =~ s/\\/\//g;
       
    33     $PerlEPOCPath .= "\/" unless $PerlEPOCPath =~ /\/$/;
       
    34     $PerlEPOCPath .= "epoc32\/tools\/";
       
    35 }
       
    36 use lib $PerlEPOCPath."build/lib/";
       
    37 use lib $PerlEPOCPath;
       
    38 use lib $PerlLibPath;
       
    39 use strict;
       
    40 use romutl;
       
    41 use romosvariant;
       
    42 # Work out the relative path to the epoc32 directory 
       
    43 use Cwd; 
       
    44 use File::Basename;
       
    45 # global variables specific to data drive image generation. 
       
    46 use File::Path ;					# Module to provide functions to remove or create directories in a convenient way.
       
    47 use File::Find; 
       
    48 use features;
       
    49 use flexmodload;	     # To load modules dynamically
       
    50 
       
    51 my $enforceFeatureManager = 0; # Flag to make Feature Manager mandatory if SYMBIAN_FEATURE_MANAGER macro is defined. 
       
    52 
       
    53 my $BuildromMajorVersion = 0 ;
       
    54 my $BuildromMinorVersion = 2;
       
    55 my $BuildromPatchVersion = 0;
       
    56 
       
    57 my $outputoby = "output.oby" ;
       
    58 
       
    59 
       
    60 sub print_usage {
       
    61 
       
    62 	# Option "-fm" will be supported instead of option "-f|fr" if SYMBIAN_FEATURE_MANAGER macro is defined.
       
    63 	my $featuresOptionUsage = "-f<featureuids> or\n".
       
    64 	"   -fr=<featureuids>            -- feature registry database XML file name\n";
       
    65 	if ($enforceFeatureManager) {
       
    66 		$featuresOptionUsage = "-fm=<featuredbfile>          -- feature manager/feature registry database XML file name.\n".
       
    67 							   "                                   Multiple XML files can be passed seperated by commas.\n".
       
    68 							   "   -nofm=<featuresdatafile>     -- don't generate features data file.\n".
       
    69 							   "                                   Instead use pre-built features data file.\n";
       
    70 	}
       
    71 
       
    72 #........1.........2.........3.........4.........5.........6.........7.....
       
    73 	print <<USAGE_EOF;
       
    74 
       
    75 FEATURECONFIGURATOR - feature configuration tool V$BuildromMajorVersion.$BuildromMinorVersion.$BuildromPatchVersion
       
    76 
       
    77 Usage:
       
    78 
       
    79   featureconfigurator [options] obyfile [obyfile2 ...]   
       
    80 
       
    81 Configurate features from *.iby/*.oby files and output a 
       
    82 consolidated obyfile for buildrom's use. 
       
    83 
       
    84 This is a front end of buildrom, which partly implements 
       
    85 functionalities of buildrom.
       
    86 
       
    87 
       
    88 
       
    89 The available options are
       
    90 
       
    91    -h                           -- Print this message
       
    92 
       
    93    $featuresOptionUsage
       
    94    -oby-charset=<charset>       -- Used character set in which OBY was written
       
    95 
       
    96    -k or -keepgoing             -- Enable keepgoing,continue to config features
       
    97                                    and create oby file.
       
    98 
       
    99    -argfile=xxx                 -- Specify argument-file name containing list of 
       
   100                                    command-line arguments to featureconfigurator
       
   101    -workdir=xxx                 -- Specify a directory for generated files. 
       
   102                                    The working directory will not be changed even this option is used.
       
   103    
       
   104    -I<directory>                -- Use <directory> for the referenced IBY/OBY files
       
   105    -D<xxx>                      -- Define xxx for C++ preprocessor
       
   106 
       
   107    -stdcpp                      -- Ignore symbian customized cpp and try to find 
       
   108                                    another cpp in the PATH.(for Windows only)
       
   109    -cpp=<xxx>                   -- Use xxx as path of CPP preprocessor.
       
   110  
       
   111    -o<xxx.oby>                  -- Output oby file name is set to xxx.oby
       
   112                                    If this argument is not given, then output oby file is
       
   113                                    "output.oby". output files are placed under workdir.
       
   114 								   
       
   115 	-s                          -- strict option, any missing files will stop buildrom
       
   116 	-v                          -- verbose
       
   117 	-noiby[=<n>]                -- if n = 0, then create iby files, otherwise don't create iby files, "-noiby=0" is default
       
   118 	-w                          -- suppress cpp warnings.
       
   119 
       
   120 USAGE_EOF
       
   121 
       
   122 }
       
   123 
       
   124 
       
   125 my $PerlEPOCPath = &get_epocroot()."epoc32\/tools\/";   # fully qualified pathname of the directory containing EPOC Perl modules
       
   126 
       
   127  
       
   128 
       
   129 my $xmlrequired = 0; # assume xml required is false. Used to determine if xml
       
   130                      # modules should be loaded.
       
   131 
       
   132 
       
   133 my @tempfiles;  	
       
   134 my $preserve = 0; 	#flag to indicate if temporary files should be preserved
       
   135 my $uppath="x";	    	# will be initialised when first needed
       
   136 
       
   137 my $epocroot = &get_epocroot;
       
   138 
       
   139 my @obyfiles;
       
   140 my $cppargs = "-nostdinc -undef";
       
   141 my $opt_k = 0;
       
   142 my $opt_v = 0; 
       
   143 my $opt_w = 0 ;
       
   144 my $strict = 0;
       
   145 my $line;
       
   146 my $errors = 0;
       
   147 my $thisdir=cwd;
       
   148 $thisdir=~s-\\-\/-go;		    # separator from Perl 5.005_02+ is forward slash
       
   149 $thisdir.= "\/" unless $thisdir =~ /\/$/;
       
   150 $thisdir =~ s-\/-\\-g if (&is_windows); 
       
   151 my $workdir = $thisdir ;
       
   152 my $rominclude = $epocroot."epoc32\/rom\/include\/";
       
   153 $rominclude = &get_epocdrive().$rominclude unless $rominclude =~ /^.:/;
       
   154 $rominclude =~s-\\-\/-g;
       
   155 
       
   156 my @xmlDBFile = ();
       
   157 my $noiby = 0;
       
   158 my @obydata;
       
   159 
       
   160 my @featurefilearray; #2d array storing names and locations of feature files in each rom image
       
   161 my @featureslist; #array of hashes, stores all the features which are to go into the feature files
       
   162 my $featurefilecount=0; #counts number of feature files in each rom image
       
   163 my $featurescount=0; #counts number of features
       
   164 my $dir; # Stores the ROM image location of features.dat/featreg.cfg files
       
   165 my $featurefilename; # Stores the name of feature file to be generated(i.e. "features.dat" or "featreg.cfg")
       
   166 
       
   167 my $featuremanager = 0; #Flag to enable support for feature manager database XML file and to generate  
       
   168 			# features data file.
       
   169 my $noFeatureManager = 0; # Flag to stop the generation of features.dat file and use pre-built features.dat if provided.
       
   170 my $preBuiltFeaturesDataFile  = ''; # To store the name of pre-built features.dat file provided with "-nofm" option.
       
   171 
       
   172 #Image Content XML file that supports specific feature to be added
       
   173 my $image_content = undef;
       
   174 #Feature list XML file that acts as database containing all features details
       
   175 my $featureXml = undef; 
       
   176 my $customizedPlat = undef; 
       
   177 
       
   178 #Summary of files(both executables and data files) currently includes 
       
   179 #	host and ROM file names, 
       
   180 #	size of the file in ROM
       
   181 #	whether the file is hidden
       
   182 # This option is added so that the above additional information is emitted by rombuild/rofsbuild tools
       
   183 # only when supplied with this option so that the existing tools don't get affected.
       
   184 my $logLevel="";
       
   185  
       
   186 
       
   187 # Feature Variation modules and data
       
   188 my %featureVariant;
       
   189 
       
   190 
       
   191 my $opt_workdir = 0; 
       
   192 my $stdcpp = 0;
       
   193 my $obycharset;
       
   194 my $cppoption = 0;
       
   195 my $preprocessor = "cpp"; 
       
   196 
       
   197 sub is_fullpath {
       
   198 
       
   199 my $path = shift ;
       
   200 	if (&is_windows) {
       
   201 		if( $path =~ /^[a-z]:/i) {
       
   202 			return 1 ;
       
   203 		}
       
   204 		elsif($path =~ /^\\/) {
       
   205 			return 1 ;
       
   206 		}
       
   207 		else {
       
   208 			return 0 ;
       
   209 		}			
       
   210 	}
       
   211 	else {
       
   212 		return 1 if($path =~ /^\//) ;
       
   213 		return 0;
       
   214 	}
       
   215 
       
   216 }
       
   217 
       
   218 sub match_obyfile
       
   219 {
       
   220 	my ($obyfile) = @_;
       
   221 	if (-f $obyfile)
       
   222 	{
       
   223 		push @obyfiles, $obyfile;
       
   224 		return 1;
       
   225 	}
       
   226 
       
   227 	# search for the oby file in the list of include directories
       
   228 	my @otherDirs = ($rominclude);
       
   229 
       
   230 	if ($featureVariant{'VALID'})
       
   231 	{
       
   232 		my $dirRef = $featureVariant{'ROM_INCLUDES'};
       
   233 
       
   234 		@otherDirs = @$dirRef if ($dirRef);
       
   235 	}
       
   236 	foreach my $dir (@otherDirs)
       
   237 	{
       
   238 		print "$dir/$obyfile\n" if ($opt_v);
       
   239 		if (-f "$dir/$obyfile")
       
   240 		{
       
   241 		    push @obyfiles, "$dir/$obyfile";
       
   242 		    return 1;
       
   243 		}
       
   244 	}
       
   245 	return 0;
       
   246 }
       
   247  
       
   248 # Subroutine to process parameter-file
       
   249 sub parameterFileProcessor
       
   250 {
       
   251 	my $paramFile = shift(@_);	
       
   252 	my @paramFileParamaters = ();	
       
   253 
       
   254 	my $fileOpenFlag = 1;
       
   255 	open FILE,"<", $paramFile or $fileOpenFlag = 0;
       
   256 	
       
   257 	if(!$fileOpenFlag)
       
   258 	{
       
   259 		print "Error: Could not open parameter-file \"$paramFile\" for reading.\n";
       
   260 		return;
       
   261 	}
       
   262 	
       
   263 	# Parse parameter-file and collect all the parameters in an array
       
   264 	while(my $line = <FILE>)
       
   265 	{
       
   266 		# Read the line till character ';'(used for providing comments in the file) or EOL
       
   267 		$line = $1 if ($line =~ /(.*);/); 
       
   268 		
       
   269 		# Split the parameters specified in a line based on white-spaces		
       
   270 		my @paramaters = split(/(\s)/,$line);	
       
   271 		
       
   272 		my $flag = 0;
       
   273 		my $argWithQuotes='';
       
   274 
       
   275 		foreach my $value (@paramaters) 
       
   276 		{	
       
   277 			# If the parameter doesn't conatian double quotes then push it 
       
   278 			# to the list of parameters.
       
   279 			if(($value !~ /\"/) && (!$argWithQuotes)) 
       
   280 			{
       
   281 				if ($value !~ /^\s*$/) 
       
   282 				{
       
   283 					push @paramFileParamaters,$value;
       
   284 				}		
       
   285 			}
       
   286 			# If the parameter is in the form  -fm="faturedb.xml" then remove
       
   287 			# double quotes and push it to the list of parameters.
       
   288 			elsif(($value =~ /\".*\"/))
       
   289 			{
       
   290 				$value =~ s/\"//g;
       
   291 				push @paramFileParamaters,$value;
       
   292 			}
       
   293 			# If the parameter is in the form  -fm="fature  db.xml" then read
       
   294 			# the parameter starting from opening quote till the closing quote.
       
   295 			elsif( ($value =~ /\"/) && $argWithQuotes) 
       
   296 			{
       
   297 				$argWithQuotes .= $value;
       
   298 				$argWithQuotes =~ s/\"//g;
       
   299 				push @paramFileParamaters,$argWithQuotes;
       
   300 				$argWithQuotes='';		
       
   301 			}
       
   302 			else
       
   303 			{
       
   304 				$argWithQuotes .= $value;
       
   305 			}
       
   306 		}		
       
   307 	}
       
   308 
       
   309 	close FILE;	
       
   310 	if (!@paramFileParamaters)
       
   311 	{
       
   312 		print "Warning: No parameters specified in paramer-file \"$paramFile\".\n";		
       
   313 		return;
       
   314 	}
       
   315 	
       
   316 	my $paramFileFlag = 1;
       
   317 
       
   318 	# Invoke subroutine "process_cmdline_arguments" to process the parameters read from
       
   319 	# the parameter file.
       
   320 	&process_cmdline_arguments($paramFileFlag, @paramFileParamaters);
       
   321 
       
   322 }
       
   323 
       
   324 # Processes the command line arguments passed to buildrom tool
       
   325 
       
   326 sub process_cmdline_arguments
       
   327 {
       
   328  
       
   329 	my ($paramFileFlag, @argList); 
       
   330 
       
   331 	if (defined @_) {
       
   332 		($paramFileFlag, @argList) = @_;
       
   333 	}
       
   334 	else {
       
   335 		if(scalar(@ARGV) == 0){
       
   336 			my @hrhMacros = &get_variantmacrolist;	
       
   337 			$enforceFeatureManager = 1 if (grep /^SYMBIAN_FEATURE_MANAGER\s*$/, @hrhMacros);
       
   338 			print_usage();
       
   339 			exit 1;				
       
   340 		}
       
   341 		
       
   342 		@argList = @ARGV;
       
   343 	}
       
   344 
       
   345 	if (!defined $paramFileFlag)  {
       
   346 	
       
   347 		# Enforce Feature Manager if macro SYMBIAN_FEATURE_MANAGER is defined in the HRH file.
       
   348 		my @hrhMacros = &get_variantmacrolist;	
       
   349 		$enforceFeatureManager = 1 if (grep /^SYMBIAN_FEATURE_MANAGER\s*$/, @hrhMacros);
       
   350 		# Process the parameters of parameter-file if passed.
       
   351 		foreach my $arg (@argList) {
       
   352 			if ($arg =~ /^-h/i) {
       
   353 				print_usage();
       
   354 				exit 1;				
       
   355 			}
       
   356 		}
       
   357 		# Process the parameters of parameter-file if passed.
       
   358 		foreach my $arg (@argList) {
       
   359 			&parameterFileProcessor($1) if ($arg =~ /^-argfile=(.*)/) ;
       
   360 		}
       
   361 	}
       
   362 	# first searching argList for keepgoing option
       
   363 	my @newArgList = () ;
       
   364 	foreach my $arg (@argList) {
       
   365 		if ( $arg =~ /^-k$/i || $arg =~ /^-keepgoing$/i ) {
       
   366 			$opt_k = 1;	 
       
   367 		}
       
   368 		elsif ($arg =~ /^-s$/) {
       
   369 			$strict = 1; 
       
   370 	    }
       
   371 		elsif ($arg =~ /^-v$/) {
       
   372 			$opt_v =1; 
       
   373 	    }
       
   374 		elsif( $arg =~ /^-w$/) {
       
   375 			$opt_w = 1 ;
       
   376 		}
       
   377 		elsif ($arg =~ /^-workdir=(.*)/) {			
       
   378 			$workdir = $1;
       
   379 			$workdir = $thisdir.$workdir unless(&is_fullpath($workdir)) ;
       
   380 			$workdir.= "\/" unless $workdir =~ /\/$/;
       
   381 			mkdir($workdir) unless (-d $workdir); 
       
   382 		}else {
       
   383 			push @newArgList, $arg ;
       
   384 		}
       
   385 	}
       
   386 	foreach my $arg (@newArgList)
       
   387 	{
       
   388 	    if ($arg =~ /^-argfile=(.*)/)  {
       
   389 			&parameterFileProcessor($1) if (defined $paramFileFlag); 
       
   390 		}
       
   391 		elsif ($arg =~ /^-DFEATUREVARIANT=(.*)/) {
       
   392 			my $varname = $1;			
       
   393 			if ($varname =~ /^\.(.*)$/) {
       
   394 				# for testing, locate the VAR file in the current directory
       
   395 				%featureVariant = get_variant($1, ".");
       
   396 			}
       
   397 			else {
       
   398 				%featureVariant = get_variant($varname);
       
   399 			}
       
   400 			if (!$featureVariant{'VALID'}) {
       
   401 			    print "FEATUREVARIANT $varname is not VALID\n";
       
   402 				$errors++;
       
   403 			}
       
   404 			if ($featureVariant{'VIRTUAL'}) {
       
   405 			    print "FEATUREVARIANT $varname is VIRTUAL\n";
       
   406 				$errors++;
       
   407 			}
       
   408 			addDrivesToFeatureVariantPaths(); 
       
   409 		}
       
   410 		elsif ($arg =~ /^-[DI]/) {
       
   411 			$cppargs .= " $arg";  
       
   412 	    } 
       
   413 	    elsif ($arg =~/^-oby-charset=(.*)$/i) {
       
   414 		$obycharset = $1; 
       
   415 	    }
       
   416 		elsif($arg =~ /^-o(.*)/i)   {
       
   417 			$outputoby = $1;  
       
   418 		} 
       
   419 		elsif ($arg =~ /^-noiby(=(\d))$/i ) {
       
   420 			if(!$1) {
       
   421 				$noiby = 1;
       
   422 			}
       
   423 			else {
       
   424 				if(!$2) {
       
   425 					print "Warning: No value for \"-noiby=\" option, use default.\n";
       
   426 				}
       
   427 				else {
       
   428 					$noiby = $2 ;
       
   429 				}
       
   430 			}
       
   431 		}
       
   432 		#Process feature manager database xml file 
       
   433 	    elsif($arg =~ /^-fm=(.*)/) {
       
   434 			if (!$enforceFeatureManager) {
       
   435 				print "Unknown arg: $arg\n";
       
   436 				$errors++;
       
   437 				next;
       
   438 			}
       
   439 			$featureXml = $1;			
       
   440 			$xmlrequired = 1;
       
   441 			$featuremanager = 1;
       
   442 			if ($featureXml =~ /^$/)  {
       
   443 				print "Error: No filename specified with \"-fm=\" option.\n";
       
   444 			} 
       
   445 			else {			
       
   446 				@xmlDBFile = split /,/,$featureXml if($noiby == 0);
       
   447 			} 
       
   448 	    }
       
   449 		elsif ($arg =~ /^-nofm(=(.*))?$/) {
       
   450 			if (!$enforceFeatureManager)  {
       
   451 				print "Unknown arg: $arg\n";
       
   452 				$errors++;
       
   453 				next;
       
   454 			}
       
   455    			$noFeatureManager = 1; 
       
   456             if(!$2) {
       
   457                 print "Warning: No filename specified with \"-nofm=\" option, feature data file might not be included.\n";
       
   458             }
       
   459             else {
       
   460                 $preBuiltFeaturesDataFile = $2;						
       
   461             } 	
       
   462 		}
       
   463 		#Process feature registry database xml file 
       
   464 	    elsif($arg =~ /^-fr=(.*)/ || $arg =~ /^-f(.*)/) {
       
   465 			if ($enforceFeatureManager)
       
   466 			{
       
   467 				print "Error: Option \"-f|-fr\" is no longer supported.\n";
       
   468 				$errors++;
       
   469 				next;
       
   470 			}			
       
   471 			$featureXml = $1;
       
   472 			$xmlrequired = 1;			
       
   473 			print "Error: No filename specified with \"-f|-fr\" option.\n" if ($featureXml =~ /^$/) ;
       
   474 	    } 
       
   475 		elsif ($arg =~ /^-stdcpp$/i) {
       
   476 			if (&is_linux) {
       
   477 				print "Warning: option -stdcpp only apply for Windows\n"; 
       
   478 			}
       
   479 			if ($cppoption) {
       
   480 				print "Error: -stdcpp option and -cpp=xxx option cannot be used at the same time.\n";
       
   481 				exit (1);
       
   482 			}
       
   483 			$stdcpp = 1; 
       
   484 		}
       
   485 		elsif ($arg =~ /^-cpp=(.*)/) {
       
   486 			if ($stdcpp) {
       
   487 				print "Error: -stdcpp option and -cpp=xxx option cannot be used at the same time.\n";
       
   488 				exit (1);
       
   489 			}
       
   490 			print "Warning: -cpp option has been set before. The previous configuration will be overwritten!\n" if ($cppoption);
       
   491 			$cppoption = 1;
       
   492 			$preprocessor = $1;
       
   493 			$preprocessor =~ s-\\-\/-g;
       
   494 			$preprocessor =~ s-EPOCROOT##\/?-$epocroot-g;
       
   495 			if (-d $preprocessor) {
       
   496 				$preprocessor .= "\/" unless $preprocessor =~ /\/$/;
       
   497 				$preprocessor .= "cpp";
       
   498 			} 
       
   499 		} 
       
   500 	    elsif ($arg =~ /^-/)  {
       
   501 			print "Unknown arg: $arg\n";
       
   502 			$errors++;
       
   503 			next;
       
   504 	    }
       
   505 		else {
       
   506 			# It's an OBY file
       
   507 			next if (match_obyfile($arg));
       
   508 			next if (match_obyfile("$arg.oby"));
       
   509 			print "Cannot find oby file: $arg\n";
       
   510 			$errors++ if(!$opt_k);
       
   511 		}	    
       
   512 	}
       
   513 
       
   514 	return if (defined $paramFileFlag) ;
       
   515 	if (@obyfiles<1 ) {
       
   516 	    print "Missing obyfile argument\n";
       
   517 	    $errors++ if(!$opt_k);
       
   518 	}
       
   519 	if(defined($obycharset)) {
       
   520 		print "Warning: Ignoring not supportted charset $obycharset, local charset will be used as default!\n" unless($obycharset =~ /utf-?8/i);
       
   521 	}
       
   522 
       
   523 	if ($errors) {
       
   524 	    print_usage();
       
   525 	    exit 1;
       
   526 	}
       
   527 	
       
   528 	if ($noFeatureManager && $featuremanager)  {
       
   529 		print "Warning: Ignoring \"-nofm\" option, as both \"-nofm\" and \"-fm\" options are provided.\n";			
       
   530 		$noFeatureManager = 0;
       
   531 	}
       
   532 
       
   533 	# Adding variant specific macros by including a HRH file
       
   534 	# (only required if no Feature Variant is used)
       
   535 	if (!$featureVariant{'VALID'}) {
       
   536 	    my $variantMacroHRHFile = get_variantmacroHRHfile();
       
   537 	    if($variantMacroHRHFile){
       
   538 	        my $variantFilePath = split_path('Path',$variantMacroHRHFile);
       
   539 	        $cppargs .= " -I " . &append_driveandquote($variantFilePath) . " -include " . &append_driveandquote($variantMacroHRHFile); 
       
   540 	        print "in cmd process $cppargs\n" if ($opt_v);
       
   541 	    }
       
   542 	}
       
   543 	# load the required modules if xml is required
       
   544 	if ($xmlrequired == 1) {
       
   545 	    load_featuresutil() if (defined ($featureXml));	    
       
   546 	}
       
   547 }
       
   548 
       
   549 #----------------------------------------------------------------------------------
       
   550 # Preprocessing phase	
       
   551 #
       
   552 # Concatentate the specified .oby files and pass them through cpp
       
   553 # to get the raw ROM specification in tmp1.oby
       
   554 
       
   555 sub preprocessing_phase
       
   556 {
       
   557 	 
       
   558 	
       
   559 	my $temp1OBYFile = $workdir."tmp1.oby";
       
   560 	unlink "$temp1OBYFile";
       
   561 
       
   562 #	Macro "ROM_FEATURE_MANAGEMENT" is defined when "-f|fr" or "-fm" is used
       
   563 	$cppargs .= " -w" if($opt_w) ;
       
   564 	$cppargs .= " -DROM_FEATURE_MANAGEMENT " if (defined ($featureXml));
       
   565 
       
   566 	# add pre-include file and include directories for feature variants
       
   567 	if ($featureVariant{'VALID'})
       
   568 	{
       
   569 		$cppargs .= " -I.";
       
   570 		my $incRef = $featureVariant{'ROM_INCLUDES'};
       
   571 		if ($incRef) {
       
   572 			foreach (@$incRef) {
       
   573 				$cppargs .= " -I \"$_\"";
       
   574 			}
       
   575 		}
       
   576 		my $HRH = $featureVariant{'VARIANT_HRH'};
       
   577 		$cppargs .= " -include \"$HRH\"" if ($HRH);
       
   578 	}
       
   579 	else {
       
   580 		# no feature variant so use the standard includes
       
   581 		$cppargs .= " -I. -I \"$rominclude\"";
       
   582 	}
       
   583 
       
   584 	$preprocessor = find_stdcpp() if ($stdcpp);
       
   585 	print "* $preprocessor -Wno-endif-labels -o $temp1OBYFile $cppargs\n" if ($opt_v);
       
   586 	
       
   587 	is_existinpath("$preprocessor", romutl::DIE_NOT_FOUND);
       
   588 	$errors = 0; 
       
   589 	open CPP, "| $preprocessor -Wno-endif-labels -o $temp1OBYFile $cppargs" or die "* Can't execute cpp";
       
   590 	foreach my $arg (@obyfiles) {
       
   591 		print CPP "\n#line 1 \"$arg\"\n";
       
   592 	
       
   593 		if(open(OBY, $arg)) {
       
   594 			print "* reading $arg\n" if ($opt_v);
       
   595 			while ($line=<OBY>) {
       
   596 				print CPP $line;
       
   597 			}
       
   598 			close OBY;
       
   599 		}
       
   600 		else {
       
   601 			print STDERR "* Can't open $arg\n";
       
   602 			if(!$opt_k){			
       
   603 				close CPP;
       
   604 				exit(1);
       
   605 			}
       
   606 		}
       
   607 	}
       
   608 	close CPP;
       
   609 	my $cpp_status = $?;
       
   610 	die "* cpp failed\n" if ($cpp_status != 0 || !-f "$temp1OBYFile");
       
   611 	
       
   612 
       
   613 	if( defined ($image_content)) {
       
   614 		#Read the OBY file that was generated by the pre-processor
       
   615 		&ReadPreprocessedFile($temp1OBYFile);
       
   616 
       
   617 #		Check if the static dependencies of the OBY binaries are resolved.
       
   618 		&ImageContentHandler::UpdateObyBinaryStaticDep();
       
   619 		
       
   620 		#Now append the files collected from cdfs.
       
   621 		&ImageContentHandler::GenObyFile($temp1OBYFile);
       
   622 	}
       
   623 
       
   624  
       
   625 	if($obycharset =~ /utf-?8/i) {
       
   626 		my $utf8file = $workdir."tmp1utf8.oby";
       
   627 		open INFILE, "<$temp1OBYFile" or die "* Can't open file $temp1OBYFile";
       
   628 		open CHARSETTRAN, "| charsettran -to=hostcharset > $utf8file" or die "* Can't execute charsetran";
       
   629 		while(<INFILE>) {
       
   630 			print CHARSETTRAN $_;
       
   631 		}
       
   632 		close CHARSETTRAN;
       
   633 		close INFILE;	
       
   634 		unlink $temp1OBYFile  or die "* Can't remove file $temp1OBYFile";
       
   635 		rename 	$utf8file, $temp1OBYFile or die "* Can't rename file $utf8file to file $temp1OBYFile";
       
   636 	}
       
   637 	
       
   638 	open TMPOBY, "<$temp1OBYFile" or die "*cpp output can not be read.\n"; 
       
   639 	@obydata = <TMPOBY> ;
       
   640 	close TMPOBY;
       
   641  
       
   642 
       
   643 	
       
   644 }
       
   645  
       
   646 sub load_featuresutil
       
   647 {
       
   648 	&FlexLoad_ModuleL("featuresutil");
       
   649 			
       
   650 	# Parse the feature database XML file
       
   651 	if(!&featuresutil::parseXMLDatabase($featureXml, $featuremanager, $strict))
       
   652 	{
       
   653 		$featureXml = undef;
       
   654 		exit(1) if($strict);
       
   655 	}
       
   656 }
       
   657 
       
   658 #----------------------------------------------------------------------------------
       
   659 # Feature registry configuration file/Features data file generation phase
       
   660 #
       
   661 # If feature registry configuration files/features data files are required then creates these files for
       
   662 # each ROM/ROFS image
       
   663 #
       
   664 sub featurefile_creation_phase
       
   665 {
       
   666 		# Set the name and Rom Image location of feature file.
       
   667 	if ($enforceFeatureManager)  {
       
   668 		# features data file location
       
   669 		$dir = "private\/10205054\/";
       
   670 		$featurefilename = "features.dat";
       
   671 	}
       
   672 	else {
       
   673 		# feature registry configuration file location
       
   674 		$dir = "private\/102744CA\/"; 
       
   675 		$featurefilename = "featreg.cfg";
       
   676 	}
       
   677 	my $onlysmrimage  = 1 ;
       
   678 	
       
   679 	foreach $line(@obydata) {		
       
   680 		if(($line =~ /^\s*romsize\s*=/i) || ( $line=~ /^\s*rom_image/i) || ($line =~ /^\s*data_image/i)) {
       
   681 			$onlysmrimage = 0;
       
   682 			last;
       
   683 		}
       
   684 	}	
       
   685 	if ($enforceFeatureManager && (!$featuremanager) && (!$noFeatureManager) ) {
       
   686 		my $defaultFeatureDbFlag = 0;
       
   687 		foreach $line(@obydata) { 
       
   688 			if ($line=~/^\s*defaultfeaturedb\s*=?\s*(\S+)/i) {	
       
   689 				# Get the default value for featuredatabasefile
       
   690 				
       
   691 				$featureXml = "$epocroot$1";
       
   692 				$featureXml =~ s-\\-\/-g;
       
   693 				$featuremanager = 1;				
       
   694 				$defaultFeatureDbFlag = 1;
       
   695 				load_featuresutil();				
       
   696 				last;
       
   697 			}
       
   698 		}
       
   699 		if(!$defaultFeatureDbFlag && !$onlysmrimage)
       
   700 		{
       
   701 			print "Error: Neither option \"-fm|-nofm\" nor default value for featuredatabase file is provided.\n";
       
   702 			exit(1);			
       
   703 		}
       
   704 	}
       
   705 	my @newobydata = ();
       
   706 	if (defined ($featureXml))  {
       
   707 		my $featurefilecount=0;
       
   708 		my $romimage=0;
       
   709 
       
   710 		foreach $line (@obydata) {
       
   711 			# specify which romimage following lines are part of
       
   712 			if ($line=~/^\s*ROM_IMAGE\[(\d)\]/) {
       
   713 				$romimage=$1;
       
   714 				$featurefilecount=0;
       
   715 			}
       
   716 			elsif ($line =~ /^\s*REM/i || $line =~ /^\s*\r?\n$/ ){
       
   717 				next ;
       
   718 				# ignore empty
       
   719 			}
       
   720 			elsif($line =~ /^\s*(FEATURE)\s*(\S*)\s*(.*)/i || $line =~ /^\s*(EXCLUDE_FEATURE)\s*(\S*)\s*(.*)/i) {
       
   721 				
       
   722 				# FEATURE  <feature_name>  [ SF  <status falgs> ] [ UD  <user data> ]
       
   723 				my $feature = $1;
       
   724 				my $featurevalue = $2;
       
   725 				my $featureargs = $3;
       
   726 				my $reservedbit = 0;
       
   727 				my %featureflags=();			 
       
   728 				# Options 'SF' and 'UD' will be supported only for "-fm" option
       
   729 				if ($featuremanager)  {
       
   730 					# [ SF  <status falgs> ] [ UD  <user data> ]
       
   731 					$featureargs =~	/(\S*)\s*(\S*)\s*(\S*)\s*(\S*)\s*/ ;
       
   732 
       
   733 					# Store the values of 'SF' and 'UD', or any invalid option, if provided					
       
   734 					$featureflags{uc($1)} = $2 if ($1);  
       
   735 					$featureflags{uc($3)} = $4 if ($3); 
       
   736 
       
   737 					# Generate a warning if the option provided with Feature/Exclude_Feature keyword is  
       
   738 					# not 'SF' or 'UD'.
       
   739 					foreach my $Key (keys %featureflags) {						
       
   740 						if ($Key !~ /^(SF|UD)$/) {
       
   741 							print "Warning: Invalid argument \"$Key\" specified for feature $featurevalue\n";
       
   742 							delete $featureflags{$Key};
       
   743 							next;
       
   744 						}						
       
   745 					}							
       
   746 				}				
       
   747 				# In verbose mode, generate warning if "SF|UD" arguments or invalid arguments are specified
       
   748 				# for "-f|fr" option.
       
   749 				elsif ($featureargs && $opt_v) {
       
   750 					print "Invalid argument(s) \"$featureargs\" provided for feature \"$featurevalue\"\n";
       
   751 					foreach my $Key (keys %featureflags) {
       
   752 						delete $featureflags{$Key};
       
   753 					}
       
   754 				}				
       
   755 				
       
   756 				# The feature file name is of the format featreg.cfg[x-y] or features.dat[x-y] 
       
   757 				# where x is the romimage id, y is always 0, reserved for future use.
       
   758 				my $targetfeaturefile;
       
   759 				if (($romimage == 0) && ($reservedbit == 0)) {
       
   760 
       
   761 					# Core image will not have the mangled name
       
   762 				 	$targetfeaturefile = $featurefilename;
       
   763 				}
       
   764 				else {
       
   765 				 	$targetfeaturefile = $featurefilename . "\[". $romimage . "\-$reservedbit\]";
       
   766 				}
       
   767 				my $flag=1;
       
   768 				my $featureflag;
       
   769 				if ($feature =~ /^FEATURE$/i) {
       
   770 					$featureflag = 1;
       
   771 				}
       
   772 				else {
       
   773 					$featureflag = 0;
       
   774 				}
       
   775 
       
   776 				my $i;
       
   777  				# loop to see if name of feature file already added to this romimage in array
       
   778 				for($i=0;$i<$featurefilecount && $flag;$i++) {
       
   779 					$flag=0 if($featurefilearray[$romimage][$i]{cfgfile} eq $targetfeaturefile);
       
   780 				}
       
   781 			
       
   782 				if($flag) { # adds feature file if not yet listed for this romimage in array
       
   783 					$featurefilearray[$romimage][$featurefilecount++]={cfgfile=>$targetfeaturefile, cfgdir=>$dir};
       
   784 					$i=$featurefilecount;
       
   785 				}
       
   786 
       
   787 				$featureslist[$featurescount]= {feature=>$featurevalue, include=>$featureflag, rom=>$romimage, cfgfile=>$i-1};
       
   788 				
       
   789 				# Store the value of 'SF' in 'featureslist' array
       
   790 				$featureslist[$featurescount]->{SF} = $featureflags{SF} if (defined $featureflags{SF}) ;
       
   791 				# Store the value of 'UD' in 'featureslist' array
       
   792 				$featureslist[$featurescount]->{UD} = $featureflags{UD} if (defined $featureflags{UD}) ;
       
   793 				$featurescount++;
       
   794 			}
       
   795 		}
       
   796 
       
   797 		# Create Feature File
       
   798 		for(my $i=0;$i<scalar @featurefilearray;$i++) {
       
   799 			my $j=0;
       
   800 			while(defined $featurefilearray[$i][$j])
       
   801 			{
       
   802 				my $targetfeaturefile = $workdir.$featurefilearray[$i][$j]{cfgfile}; 
       
   803 				if (!(&featuresutil::createFeatureFile($i,$j,$targetfeaturefile,\@featureslist,$featuremanager)))  {
       
   804 					$featurefilearray[$i][$j]{cfgfile}= undef;
       
   805 					exit(1) if($strict);					
       
   806 				}
       
   807 				$j++;
       
   808 			}
       
   809 		} 
       
   810 		my $flag=1;
       
   811         	my $imageIdx=0;
       
   812 
       
   813 		# Add feature files to ROM image, adds lines to obey file to specify existing locations
       
   814 		# of feature files and target locations. 
       
   815 		
       
   816 		# features.dat will be written to the end of rom/rofs
       
   817 		my @lastFLs = ();
       
   818 		my $lastRomIndex = 0 ;
       
   819 		
       
   820 		foreach $line (@obydata) {
       
   821 			if($line =~/^\s*ROM_IMAGE\[(\d)\]/i) {
       
   822 				my $index=$1;
       
   823 						
       
   824 				if($lastRomIndex != $index) {
       
   825 					foreach my $fl(@lastFLs) {
       
   826 						push @newobydata,$fl ;
       
   827 					}
       
   828 					@lastFLs = ();
       
   829 					$lastRomIndex = $index ;
       
   830 				}
       
   831 				push @newobydata, "\n" . $line . "\n";	
       
   832 				my $j=0;
       
   833 				while(defined $featurefilearray[$index][$j]) {
       
   834 					$flag = 0 if($index == 0);
       
   835 					# Put in feature files for current ROM_IMAGE
       
   836 					my $targetfeaturefile = $featurefilearray[$index][$j]{cfgfile};
       
   837 					# Rom images will not have mangled name for feature files
       
   838 				 					
       
   839 					# Rofsbuild will set attribute 'exattrib=U' in the entry record when this field is used.
       
   840 					# File Server when asked for a directory listing would notice the attribute and will return the 
       
   841 					# list with mangled names. Hence, mangled name for feature files should not be put in ROM_IMAGE.
       
   842 					my $exattribute = "" ;					
       
   843 					if (defined $targetfeaturefile ) {
       
   844 						$exattribute = "exattrib=U" if($index > 0);
       
   845 						push @lastFLs, "ROM_IMAGE[$index] data=" . $workdir . $targetfeaturefile . " \"". $featurefilearray[$index][$j]{cfgdir} .$featurefilename .  "\"\t\t" . $exattribute . "\n";
       
   846 						$featurefilearray[$index][$j]{cfgfile} = undef ;
       
   847 					}
       
   848 					$j++;
       
   849 				}
       
   850 			}
       
   851 			elsif($line !~ /^\s*(FEATURE)\s*/i && $line !~ /^\s*(EXCLUDE_FEATURE)\s*/i && $line !~/^\s*defaultfeaturedb\s*=?\s*(\S+)/i) {
       
   852 				# Put in all other lines except the FEATURE and EXCLUDE_FEATURE keywords
       
   853 				push @newobydata, $line;
       
   854 			}
       
   855 			else {
       
   856 				push @newobydata, " "; 
       
   857 			}
       
   858 			 
       
   859 		}
       
   860 		foreach my $fl(@lastFLs) {
       
   861 			push @newobydata,$fl ;
       
   862 		}
       
   863 		if($flag) { 
       
   864 			# Put in feature files for ROM_IMAGE[0] if it is the only ROM_IMAGE
       
   865 			my $k=0;
       
   866 			while(defined $featurefilearray[0][$k])
       
   867 			{ 
       
   868 				my $targetfeaturefile = $featurefilearray[0][$k]{cfgfile};
       
   869 				if (defined $targetfeaturefile)
       
   870 				{
       
   871 					push @newobydata, "data=" . $workdir . $targetfeaturefile . " \"" . $featurefilearray[0][$k]{cfgdir} . $targetfeaturefile . "\"\n";
       
   872 					$featurefilearray[0][$k]{cfgfile} = undef ;
       
   873 				}
       
   874 				$k++;
       
   875 			}
       
   876 		}
       
   877 	}
       
   878 	elsif ($enforceFeatureManager && $noFeatureManager && $preBuiltFeaturesDataFile) {
       
   879         print "Valid: $preBuiltFeaturesDataFile\n";
       
   880 		if (-e $preBuiltFeaturesDataFile)  { 
       
   881 			my $flag = 1;
       
   882 			foreach my $line (@obydata)
       
   883 			{
       
   884 				# Put in the pre-built features data file in ROM_IMAGE[0] 
       
   885 				if($line =~/^\s*ROM_IMAGE\[1\]/i)
       
   886 				{
       
   887 					push @newobydata, "data=$preBuiltFeaturesDataFile" . " \"" . $dir . $featurefilename . "\"\n";
       
   888 					$flag =0;
       
   889 				}
       
   890 				push @newobydata, $line;
       
   891 			}
       
   892 			if($flag)
       
   893 			{ 
       
   894 				# Put in the pre-built features data file in ROM_IMAGE[0] if it is the only ROM_IMAGE
       
   895 				push @newobydata, "data=$preBuiltFeaturesDataFile" . " \"" . $dir . $featurefilename . "\"\n";
       
   896 			}
       
   897 		}
       
   898 		else
       
   899 		{
       
   900 			print "Error: File \"$preBuiltFeaturesDataFile\" doesn't exist.\n";
       
   901 			exit(1);
       
   902 		}
       
   903 	}
       
   904 	elsif ($enforceFeatureManager) {
       
   905 	    print "Error: no feature data file or pre-built feature data file is provided!";
       
   906 	    exit(1);
       
   907 	}
       
   908 	
       
   909 		my $output ;
       
   910 	if(&is_windows) {
       
   911 		if($outputoby =~ /^[\\\/]/ || $outputoby =~ /^[a-zA-Z]:/)  {
       
   912 			$output = $outputoby ;
       
   913 		}
       
   914 		else {
       
   915 			$output = $workdir.$outputoby;
       
   916 		}
       
   917 	}
       
   918 	else {
       
   919 		if($outputoby =~ /^[\/]/ )  {
       
   920 			$output = $outputoby ;
       
   921 		}
       
   922 		else {
       
   923 			$output = $workdir.$outputoby;
       
   924 		}
       
   925 	} 
       
   926 	unlink $output if(-e $output);
       
   927 	print "* Writing $output...\n" if($opt_v);
       
   928 	unless(open FOUT, ">$output"){
       
   929 		print "Error: Can not write to $output.\n";
       
   930 		exit(1);
       
   931 	}
       
   932 	foreach(@newobydata){
       
   933 		chomp ;
       
   934 		print FOUT "$_\n";
       
   935 	} 
       
   936 	close FOUT ; 
       
   937 	print "* Done.\n" if($opt_v);
       
   938 }
       
   939 
       
   940 # make sure that all the absolute feature variant paths include a
       
   941 # drive letter. This is required because cpp will not work with
       
   942 # absolute paths starting with slashes.
       
   943 sub addDrivesToFeatureVariantPaths
       
   944 {
       
   945 	return unless $featureVariant{'VALID'};
       
   946 
       
   947 	my $current = &get_epocdrive;
       
   948 	my $drive = $1 if ($current =~ /^(.:)/);
       
   949 
       
   950 	# pre-include file
       
   951 	my $HRH = $featureVariant{'VARIANT_HRH'};
       
   952 	$featureVariant{'VARIANT_HRH'} = $drive . $HRH if ($HRH =~ /^[\\\/]/);
       
   953 
       
   954 	# ROM include path
       
   955 	my $dirRef = $featureVariant{'ROM_INCLUDES'};
       
   956 	return unless $dirRef;
       
   957 	my $i = 0;
       
   958 
       
   959 	foreach my $dir (@$dirRef)
       
   960 	{
       
   961 		$$dirRef[$i] = $drive . $dir if ($dir =~ /^[\\\/]/);
       
   962 		$i++;
       
   963 	}
       
   964 }
       
   965 #
       
   966 # Process the given absolute path
       
   967 # Add backslash at the end if required
       
   968 # @param - path to be processed
       
   969 #
       
   970 sub processPath
       
   971 {
       
   972 	my ($path) = shift;
       
   973 	
       
   974 	return if( $$path =~ /(\\$)/ );
       
   975 	return if( $$path =~ /(\/$)/ );
       
   976 	$$path .= "/";
       
   977 }
       
   978 
       
   979 # Main block for buildrom module invocation
       
   980 
       
   981 
       
   982 # Processes the buildrom command line parameters.
       
   983 &process_cmdline_arguments; 
       
   984 if(scalar(@xmlDBFile) > 0) { 
       
   985 	&processPath(\$epocroot);
       
   986 	&processPath(\$thisdir);
       
   987 	&features::set_DefaultPath($epocroot, \$thisdir, \$thisdir, \$thisdir, \$thisdir);
       
   988 	if(&features::open_Database(@xmlDBFile)) {  
       
   989 		&features::generate_Obeyfile($workdir);	 
       
   990 	}
       
   991 }
       
   992 #Preprocessing phase
       
   993 &preprocessing_phase; 
       
   994 # Creates feature registry configuration file/features data file.
       
   995 &featurefile_creation_phase;
       
   996 
       
   997 
       
   998 1;