#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# $Source: src/usr/hwpf/fapi/fapiCreateFapiSpyIds.pl $
#
# OpenPOWER HostBoot Project
#
# COPYRIGHT International Business Machines Corp. 2012,2014
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
use strict;
use warnings;
#------------------------------------------------------------------------------
# Print Command Line Help
#------------------------------------------------------------------------------
my $numArgs = $#ARGV+1;
print $numArgs;
if ($numArgs < 2)
{
print ("Usage: fapiCreateFapiSpyIds.pl \n");
print (" This script will parse the spy id files and create a set of nested\n");
print (" structures in the file fapiSpyIds.H which the FSP will use.\n");
exit(1);
}
#------------------------------------------------------------------------------
# Globals
#------------------------------------------------------------------------------
my $spyIdFile = $ARGV[0];
my $outDir = $ARGV[1];
my $outFile = "fapiSpyIds.H";
my $UTFile = "fapiSpyIdsUT.C";
$outFile = $outDir . $outFile;
my %structureNames;
my $somenumber;
my %currentmembers;
#------------------------------------------------------------------------------
# Prototypes
#------------------------------------------------------------------------------
sub buildStructures( \@ );
sub createTest();
sub addTest($$);
sub closeTest();
#------------------------------------------------------------------------------
# Open input and output files for our use.
#------------------------------------------------------------------------------
open(IDFILE, "<", $spyIdFile) or die "ERROR $? : cant open $spyIdFile : $!";
open(OUTFILE, ">", $outFile) or die "ERROR $? : can't open $outFile : $!";
open(UTFILE, ">", $UTFile) or die "ERROR $? : can't open $outFile : $!";
# direct the printf output to the file
select OUTFILE;
#select STDOUT;
createTest();
# read in the entire file to an array
my (@lines) = ;
#------------------------------------------------------------------------------
# Process every line in the file one at a time
#------------------------------------------------------------------------------
foreach my $line (@lines)
{
$line =~s/^\s+|\s+$//g;
my @tokens = split(/,/, $line );
$tokens[1]=~s/\}//;
$tokens[1]=~s/\"//g;
# replace a # with __P__
$tokens[1]=~s/\#/__P__/g;
# fix a case like this ABC.2CD ==> ABC._2CD
$tokens[1]=~s/(\.)([0-9])/$1_$2/;
#get rid of the parens
$tokens[0]=~s/\{//;
my $structure=$tokens[1];
my $number=$tokens[0];
#create a hash for later use
$structureNames{ $structure } = $number;
}
#sort the hash based on the structure name
my @keys = sort { ( $a cmp $b); } ( keys %structureNames );
my @array = @keys;
#init the key to some value..
my $current = @keys;
my @name;
my @spaces;
push(@spaces," ");
push(@spaces," ");
# start the file off with a namespace
printf "#ifndef __FAPI_SPY_IDS_H__\n";
printf "#define __FAPI_SPY_IDS_H__ \n\n";
printf "namespace FAPI_SPY_NAMES \n { \n\n";
# look at every entry in the array of names..
foreach my $value (@array)
{
# segment the name and then search for all
# entries which have the first value the same
# and then process those values
my @members = split(/\./, $value );
my $member = $members[0];
@name = ();
my $size = @members;
#once we go in here we wont need to look at this value again
if( $member ne $current )
{
push(@name,$member);
if( $size > 1 )
{
# add some readability;
printf "@spaces";
my $extern = "extern struct " . $member . "_component \n";
printf "$extern";
printf "@spaces";
printf"{\n";
# grab every value out of the array which matches our query
my @selected = @keys;
@selected = grep( m/^$member\b/, @selected);
# modify the stucture names to remove the first member
my @filtered = map { (my $new = $_) =~ s/$member\.//; $new} @selected;
$current = $member;
# passing the shortend structure names
buildStructures( @filtered );
printf "@spaces";
printf"} $member;\n";
}
else
{
# make the structure back into a name and use it go get
# the value from the hash we made eariler -- its a global
my $name = join(".", @name );
my $number = 0;
$number = $structureNames{ $name };
my $struct = "struct " . $member . "_comp";
addTest( $name, $number );
printf "@spaces";
printf "$struct\n";
printf "@spaces";
printf "{\n";
printf "@spaces";
printf" static const unsigned int value = $number;\n";
printf "@spaces";
printf "} $member;\n";
}
}
}
# close out the namespace in the file
printf "};\n";
printf "#endif\n";
close OUTFILE;
close IDFILE;
closeTest();
#done
#------------------------------------------------------------------------------
# Subroutines
#------------------------------------------------------------------------------
sub buildStructures( \@ )
{
my( $structures ) = @_;
my @structures = @$structures;
my $current = 0;
my $member = 0;
push( @spaces, " " );
push( @spaces, " " );
foreach my $value (@structures )
{
my @members = split(/\./, $value );
my $member = $members[0];
push( @name, $member );
my $size = @members;
#once we go in here we wont need to look at this value again
if( $member ne $current )
{
if( $size > 1 )
{
$somenumber += 1;
my $struct = "struct " . $member . "_comp" . $somenumber . "\n";
printf "@spaces";
printf $struct;
printf "@spaces";
printf "{\n";
# grab every value out of the array which matches our query
my @selected = grep( m/^$member\b/, @structures);
my @filtered = map { (my $new = $_) =~ s/$member\.//; $new} @selected;
$current = $member;
buildStructures( @filtered );
#take off the last struture member name
#from the array
printf "@spaces";
printf ("} $member;\n");
}
else
{
# make the structure back into a name and use it go get
# the value from the hash we made eariler -- its a global
my $name = join(".", @name );
my $number = 0;
$number = $structureNames{ $name };
my $struct = "struct " . $member . "_comp";
addTest( $name, $number );
printf "@spaces";
printf "$struct\n";
printf "@spaces";
printf "{\n";
printf "@spaces";
printf" static const unsigned int value = $number;\n";
printf "@spaces";
printf "} $member;\n";
}
}
pop(@name);
}
pop( @spaces );
pop( @spaces );
}
sub createTest()
{
printf( UTFILE "#include \n");
printf( UTFILE "#include \"s1_reduced.h\"\n\n");
printf( UTFILE "#include \n\n");
printf( UTFILE "#define fspSpyId(DATA) FAPI_SPY_NAMES::DATA.value\n");
printf( UTFILE "int main( void )\n { \n");
printf( UTFILE "unsigned int totalTests = 0; \n");
printf( UTFILE "unsigned int failedTests = 0; \n");
}
sub closeTest()
{
printf( UTFILE "if( failedTests )\n { \n");
printf( UTFILE "std::cout << failedTests << \" of \" << totalTests << \" tests failed \" << std::endl;" );
printf( UTFILE "}\n");
printf( UTFILE "else { std::cout << \"+++++ SUCCESS +++++\" << std::endl; \
std::cout << totalTests << \" TESTS PASSED\" << std::endl; }" );
printf( UTFILE "\n\n}\n");
close(UTFILE);
}
sub addTest( $$ )
{
my( $name, $number ) = @_;
# create a name which the FSP understands
my $fspName = $name;
$fspName =~ s/__P__/_/g;
$fspName =~ s/\._/\./g;
$fspName =~ s/\./_/g;
$fspName = "SPY_" . $fspName;
$fspName =~ s/ //g;
# $fspName =~ s/__/_/g;
printf( UTFILE "totalTests++; if ( fspSpyId( $name ) != $fspName)\n");
printf( UTFILE "{ std::cout << \"spy values dont match\" << std::endl; failedTests++; }\n");
}