Stderr to a file - avoid xml problems in error messages.
#
# 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 parser
my @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 flag
my $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 routine
sub 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 names
sub 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 file
sub 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;