common/tools/sysModelFilter.pl
author Simon Howkins <simonh@symbian.org>
Thu, 10 Dec 2009 12:01:59 +0000
changeset 825 1de547e13d13
parent 457 991d89a55c87
child 1316 0b4a09013baf
permissions -rw-r--r--
Updates to make the build environment check more reasonable: Mercurial v1.3 permitted The Java compiler is not a showstopping issue 7-zip can be installed in any location Update to Helium 5 Helium can be installed in PDT 1.*, not necessarily 1.0 Raptor installation path not significant Update to Raptor 2.9.* The Raptor patch to update the bundled version of python is no longer relevant BRAG calculations updated to ignore items not being in the system path, as this just doesn't matter. Overall effect is that the build environment check should pass on a machine that is able to do a build!

#!perl -w

use strict;

use XML::Parser;

my $sysModel = shift or die "First arg must be system model xml file";
my @filters = @ARGV or die "Subsequent arg(s) must be filter(s) to apply";

# Sort out the positive and negative filters specified
my @negativeFilters;
my @positiveFilters;
foreach my $filter (@filters)
{
	if ($filter =~ m{^!(.*)})
	{
		push @negativeFilters, $1;
	}
	else
	{
		push @positiveFilters, $filter;
	}
}

# Read input tree
my $parser = new XML::Parser(Style => "Objects") or die;
my $sysTree = eval { $parser->parsefile($sysModel) } or die "Failed to parse $sysModel : $@";

# Apply filter
filterTree($sysTree->[0], \@negativeFilters, \@positiveFilters);

# Output total tree
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
printTree($sysTree->[0]);
print "\n";

exit;

sub filterTree
{
	my $tree = shift;
	my $negativeFilters = shift;
	my $positiveFilters = shift;

	if (exists $tree->{filter})
	{
		# Work out how this item in the tree is tagged for filtering
		my $itemTags = [split ",", $tree->{filter}];
		my @negativeTags;
		my @positiveTags;
		foreach my $tag (@$itemTags)
		{
			if ($tag =~ m{^!(.*)})
			{
				push @negativeTags, $1;
			}
			else
			{
				push @positiveTags, $tag;
			}
		}

		# Test whether this item should be removed
		if (intersect(\@positiveTags, $negativeFilters) ||
		    intersect(\@negativeTags, $positiveFilters) )
		{
			# It should!
			# Return false, and the removal will be executed by the
			# calling instance
			# (No need to examine children)
			return 0;
		}

		# Tidy up the filter attribute
		# Remove tags from this item that have been "used up"
		# Remove the filter attribute entirely if they have all been
		# used up
		my %filterLookup = map { $_ => 1 } (@$negativeFilters, @$positiveFilters);
		@$itemTags = grep { !exists $filterLookup{$_} } @$itemTags;
		if (scalar @$itemTags)
		{
			$tree->{filter} = join ",", @$itemTags;
		}
		else
		{
			delete $tree->{filter};
		}
	}

	# Now iterate through the children of this item and remove any that
	# should be filtered out
	@{$tree->{Kids}} = grep {
		filterTree($_, $negativeFilters, $positiveFilters)
	} @{$tree->{Kids}};

	# Return true so that the calling instance will preserve this item in
	# the output tree
	return 1;
}

# Test whether two sets (arrays) intersect
sub intersect
{
	my $set1 = shift;
	my $set2 = shift;

	my %set1 = map { $_ => 1 } @$set1;
	foreach (@$set2)
	{
		return 1 if exists $set1{$_};
	}
	return 0;
}

sub printTree
{
	my $tree = shift or die;
	die unless ref $tree;

	my $tagName = ref $tree;
	$tagName =~ s{^main::}{};
	if ($tagName eq "Characters")
	{
		print $tree->{Text};
		return;
	}
	
	print "<$tagName";

	foreach my $attr (
		sort {
			my $order = "unofficial name long-name tech_domain level span schema levels filter introduced deprecated purpose class plugin origin-model bldFile mrp version priority";
			my $ixA = 1 + index $order, $a or die $a;
			my $ixB = 1 + index $order, $b or die $b;
			$ixA - $ixB;
		}
		grep {
			! ref $tree->{$_}
		}
		keys %$tree)
	{
		print " $attr=\"$tree->{$attr}\"";
	}

	my $children = $tree->{Kids};
	if (scalar @$children)
	{
		print ">";
		foreach my $child (@$children)
		{
			printTree($child);
		}
		print "</$tagName";
	}
	else
	{
		print "/"
	}

	print ">";
}