## Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).# All rights reserved.# This component and the accompanying materials are made available# under the terms of the License "Eclipse Public License v1.0"# which accompanies this distribution, and is available# at the URL "http://www.eclipse.org/legal/epl-v10.html".## Initial Contributors:# Nokia Corporation - initial contribution.## Contributors:## Description: #package featuresutil;require Exporter;@ISA = qw(Exporter);@EXPORT = qw( parseXMLDatabase createFeatureFile convert_FeatRegToFeatMgr);use strict;use XML::Handler::XMLWriter;use IO;use featureparser;use featuremanager;use featureregistry;use featuresdat;use featurecfg;my $xmlDBHandle = undef; #Object of feature parsermy @includeFeatureList; #List of included features. The included feature in this list is a hash table giving the #Uid or the name. These features are collected from the iby/obey files.my @excludeFeatureList; #List of excluded features.The excluded feature in this list is a hash table giving the #Uid or the name. These features are collected from the iby/obey files.my $verboseFlg = 0; # verbose mode flagmy $strictFlg = 1; # strict mode flag# Subroutine to generate warning messages.sub WARN { print "WARNING: ".$_[0]."\n"; }# Subroutine to generate error messages.sub ERROR { print "ERROR: ".$_[0]."\n"; }# Verbose mode output routinesub MSG { if($verboseFlg) { print "**".$_[0]."...\n"; }}# Subroutine to parse feature list XML database file.# @param dbfileList - List of XML database file names seperated by commas.# @param fmFlag - Flag to generate features data file.# @param strictFlg - Flag to enable strict mode (optional).# @param verboseFlg - Flag to enable verbose mode (optional).sub parseXMLDatabase{ my $dbfileList = shift; my $fmFlag = shift; $strictFlg = shift; $verboseFlg = shift; # list of xml databases my @filelist = split(/,/,$dbfileList); # return status my $retStatus = 0; # default mode is strict $strictFlg=0 if(!defined $strictFlg); # default mode is nonverbose $verboseFlg=0 if(!defined $verboseFlg); # multiple file support is not applicable for feature registry option if( (@filelist > 1) && (!$fmFlag) ) { &ERROR("Multiple XML database file support is not applicable for featureregistry option"); return 0; } if($fmFlag) # Feature manager option handling { # create the object of feature manager class $xmlDBHandle = new featuremanager; if($xmlDBHandle) { foreach my $file (@filelist) { my $status = 1; if(-e $file) { &MSG("Parsing $file"); # parse the feature manager xml file $status = $xmlDBHandle->parseXMLFile($file); if(! $status) { # create the object of feature registry class my $registryObj = new featureregistry; # parse the feature registry xml file $status = $registryObj->parseXMLFile($file); if($status < 0) { if($strictFlg) { &ERROR("Invalid features database $file"); $xmlDBHandle = undef; return 0; } else { &WARN("Invalid features database $file"); } } elsif(! $status) { # if the xml file is not valid feature list xml file if($strictFlg) { &ERROR("Error in reading features database file \"$file\""); $xmlDBHandle = undef; return 0; } else { &WARN("Error in reading features database file \"$file\""); } } else { MSG("Converting featureregistry database to featuremanager"); # add the feature registry file object to the feature manager file object if(! $xmlDBHandle->addFeatureRegistry($registryObj)) { if($strictFlg) { MSG("Error in reading features database file \"$file\""); $xmlDBHandle = undef; return 0; } else { &WARN("Error in reading features database file \"$file\""); } } else { # parsing feature registry database success $retStatus = 1; } } } elsif( $status < 0 ) { if($strictFlg) { &ERROR("Invalid features database $file"); $xmlDBHandle = undef; return 0; } else { &WARN("Invalid features database $file"); } } else { # parsing feature manager database success $retStatus = 1; } } else { if(!$strictFlg) { &WARN($file." doesn\'t exist"); next; } else { &ERROR($file." doesn\'t exist"); $xmlDBHandle = undef; return 0; } } } } else { &ERROR("Couldn't create feature parser object"); } } else # Feature registry file handling { if(@filelist) { my $file = $filelist[0]; $xmlDBHandle = new featureregistry; if($xmlDBHandle) { if(-e $file) { MSG("Parsing $file"); my $status = $xmlDBHandle->parseXMLFile($file); if($status < 0) { &ERROR($file." is invalid feature registry file"); $xmlDBHandle = undef; return 0; } elsif(!$status) { &ERROR("Error in reading feature registry file ".$file); $xmlDBHandle = undef; } else { # parsing feature registry database success $retStatus = 1; } } else { if(!$strictFlg) { &WARN($file." doesn\'t exist -- "); } else { &ERROR($file." doesn\'t exist -- "); } $xmlDBHandle = undef; } } else { &ERROR("Couldn't create feature parser object"); } } } if($retStatus) { return $xmlDBHandle } else { return $retStatus; }}# Subroutine to generate feature manager database file from the given feature registry database# @param strictFlg - strict mode flag# @param verboseFlg - verbose mode flag# @param outpath - destination path for the converted database file(s)# @param dblist - list of xml file namessub convert_FeatRegToFeatMgr{ $strictFlg = shift; $verboseFlg = shift; my $outpath = shift; my @dblist = @_; # default mode is strict $strictFlg=0 if(!defined $strictFlg); # default mode is nonverbose $verboseFlg=0 if(!defined $verboseFlg); foreach my $file (@dblist) { # Create the object of feature registry my $fileHandle = new featureregistry; if(-e $file) { # Parse the database if($fileHandle->parseXMLFile($file) > 0) { MSG("Converting Feature Registry database $file"); # Create directory if it doesn't exists if(!(-e $outpath)) { if(!mkdir($outpath)) { &ERROR("Failed to create $outpath folder"); return 0; } } # Emit the contents of feature registry object into an feature manager database file &generateXML($fileHandle, $outpath); } } else { if(!$strictFlg) { &WARN($file." doesn\'t exist -- "); next; } else { &ERROR($file." doesn\'t exist -- "); return 0; } } }}# Subroutine to emit XML output for the given featureregistry object# @param frObject - object of feature registry database# @param outPath - destination path for the converted database filesub generateXML{ my ($frObject, $outPath) = @_; my $outputFile = $frObject->fileName(); # Extract absolute file name if( $outputFile =~ /[\\\/]/) { $outputFile =~ /.*[\\\/](.+)\z/; $outputFile = $1; } # Add suffix _converted $outputFile =~ s/(.*)([\.].+)\z/$1_converted$2/; my $fileHandle = new IO::File(">$outPath$outputFile"); if($fileHandle) { my $writer = XML::Handler::XMLWriter->new(Output => $fileHandle); # Header $writer->start_document(); $writer->print("<!--Converted from the feature registry ".$frObject->fileName()."-->\n\n"); # DOCTYPE $writer->print("<!DOCTYPE featuredatabase SYSTEM \"featuredatabase.dtd\">\n\n"); # Root element begin $writer->start_element({Name => 'featuredatabase', Attributes => {}}); # FeatureSet element $writer->print("\n\t"); $writer->start_element({Name => 'featureset', Attributes => {}}); my $nameuidmap = $frObject->featureNameUidMap(); foreach my $uid (sort(values %$nameuidmap)) { my $featinfo = $frObject->getFeatureInfo($uid); my %attributes = (); $attributes{uid} = sprintf("0x%08X",$uid); $attributes{statusflags} = "0x00000001"; $attributes{name} = $featinfo->{name}; $writer->print("\n\t\t"); $writer->start_element({Name => 'feature', Attributes => \%attributes}); $writer->end_element({Name => 'feature'}); } $writer->print("\n\t"); $writer->end_element({Name => 'featureset'}); # defaultfeaturerange element my $rangeList = $frObject->defaultRangeList(); foreach my $range (@$rangeList) { my %attributes = (); next if(lc($range->{support}) eq "exclude"); $attributes{higheruid} = sprintf("0x%08X",$range->{max}); $attributes{loweruid} = sprintf("0x%08X",$range->{min}); $writer->print("\n\t"); $writer->start_element({Name => 'defaultfeaturerange', Attributes => \%attributes}); $writer->end_element({Name => 'defaultfeaturerange'}); } # Root element close $writer->print("\n"); $writer->end_element({Name => 'featuredatabase'}); # Footer $writer->end_document(); } else { &ERROR("Failed to create $outPath$outputFile file"); }}# Subroutine to create Feature Registry/Features Data file# @param romimage - Rom image number.# @param featurefile - Feature file number.# @param featurefilename - Name of the feature file to be generated.# @param featureslist - Reference to array of hashes containing features to included/excluded.# @param featuremanager - Flag to generate features data file.# @param singleDATfile - Flag to generate single features.dat file.sub createFeatureFile{ if($xmlDBHandle == undef) { ERROR("No XML Database opened"); return 0; } my ($romimage,$featurefile,$featurefilename,$featureslist,$featuremanager,$singleDATfile) = @_; # Default setting for singleDATfile flag $singleDATfile = 0 if(!defined $singleDATfile); # Clear the global include/exclude feature list. @includeFeatureList = (); @excludeFeatureList = (); for(my $k=0;$k<scalar @$featureslist;$k++) { if(($singleDATfile) || ($featureslist->[$k]{rom}==$romimage && $featureslist->[$k]{cfgfile} == $featurefile)) { AddToFeatureList($featureslist->[$k],$featuremanager); } } my $features = &featureparser::getFeatures(\@includeFeatureList, \@excludeFeatureList); if (!$features) { ERROR("No feature file generated for ROM_IMAGE[".$romimage."]"); return 0; } else { my $object; if ($featuremanager) { $object = new featuresdat($xmlDBHandle); } else { $object = new featurecfg($xmlDBHandle); } return $object->createFile($featurefilename, $features , $featuremanager); } }# Subroutine to add the feature specified to the included/excluded feature list# @param featureData - Reference to hash containing feature information (i.e. name/uid,# included/excluded,SF and UD). # @param featuremanager - Flag to generate features data file.sub AddToFeatureList{ my ($featureData, $featuremanager) = @_; my %feat = (); my $feature = $featureData->{feature}; # Check if the given value is a feature name. my $value = $xmlDBHandle->getFeatureUID($feature);# If not a feature, then may be uid value if(!defined $value) { if (!featureparser::IsValidNum($feature)) { ERROR("Feature \"".$feature."\" not found in feature list XML"); return; } if (&featureparser::ValidateUIDValue($feature)) { my $featureUid = $feature; $feature = &featureparser::ConvertHexToDecimal($feature); my $featureInfo = $xmlDBHandle->getFeatureInfo($feature); if (!$featureInfo) { ERROR("Feature \"".$featureUid."\" not found in feature list XML"); return; } else { $feat{uid} = $feature; $feat{name} = $featureInfo->{name}; } } else { return; } } else { $feat{name} = $feature; $feat{uid} = $value; } # Set the values of "SF" and "UD" for feature manager. if ($featuremanager) { &setFeatureArguments(\%feat,$featureData->{SF},$featureData->{UD}); } if($featureData->{include} == 1) { $feat{include} = 1; push @includeFeatureList, \%feat; } else { $feat{exclude} = 1; push @excludeFeatureList, \%feat; }}# Subroutine to set the values of "SF" and "UD" for the specified feature# @param feat - Reference to hash containing information(i.e. name and uid) # of the specified feature.# @param SF - Value of "SF" provided in the iby/oby file. # @param UD - Value of "UD" provided in the iby/oby file.sub setFeatureArguments{ my($feat,$SF,$UD)= @_; my $featureInfo = $xmlDBHandle->getFeatureInfo($feat->{uid}); # If the values of 'SF' and 'UD' are not provided in the iby/oby file, then take the values # from Feature Database XML file. if ($SF && featureparser::IsValidNum($SF)) { $feat->{SF} = &featureparser::ConvertHexToDecimal($SF); } else { # Generate warning if the value of "SF" provided for the feature in iby/oby file # is invalid. if ($SF) { WARN("Invalid SF value \"$SF\" provided for feature \"$feat->{name}\". Defaulting to value provided in XML file"); } $feat->{SF} = &featureparser::ConvertHexToDecimal($featureInfo->{statusflags}); } if ($UD && featureparser::IsValidNum($UD)) { $feat->{UD} = &featureparser::ConvertHexToDecimal($UD); } else { # Generate warning if the value of "UD" provided for the feature in iby/oby file # is invalid. if ($UD) { WARN("Invalid UD value \"$UD\" provided for feature \"$feat->{name}\". Defaulting to value provided in XML file"); } $feat->{UD} = &featureparser::ConvertHexToDecimal($featureInfo->{userdata}); } }1;