#! /usr/bin/env perl
# Class mapping
%ShortClassName = ( "Info" => "info",
"Win" => "win",
"Request" => "req",
"Comm" => "comm",
"Datatype" => "dtype",
"Intercomm" => "inter",
"Intracomm" => "intra",
"Op" => "op",
"File" => "file",
"Grequest" => "greq",
"Errhandler" => "errh",
"Status" => "st",
"base" => "",
"Prequest" => "preq",
"Group" => "group",
"Cartcomm" => "cart",
"Graphcomm" => "graph",
);
%SkipRoutines = ( "Intracomm-Spawn" => 1,
"Intracomm-Spawn_multiple" => 1,
"base-Init_thread" => 1,
"base-Init" => 1,
);
# These functions are primarily from MPI-1, and follow a differnt rule.
# ?? Should these have a place in the definition file instead of here?
%FuncHasClassAtEnd = (
"comm-Send" => 1,
"comm-Ssend" => 1,
"comm-Rsend" => 1,
"comm-Bsend" => 1,
"comm-Isend" => 1,
"comm-Issend" => 1,
"comm-Irsend" => 1,
"comm-Ibsend" => 1,
"comm-Irecv" => 1,
"comm-Send_init" => 1,
"comm-Bsend_init" => 1,
"comm-Rsend_init" => 1,
"comm-Ssend_init" => 1,
"comm-Recv_init" => 1,
"dtype-Create_contiguous" => 1,
"dtype-Create_vector" => 1,
"dtype-Create_indexed" => 1,
"inter-Gather" => 1,
"inter-Allgather" => 1,
"inter-Scatter" => 1,
"inter-Alltoall" => 1,
"inter-Gatherv" => 1,
"inter-Allgatherv" => 1,
"inter-Scatterv" => 1,
"inter-Alltoallv" => 1,
"inter-Allreduce" => 1,
"inter-Reduce" => 1,
"inter-Bcast" => 1,
"intra-Gather" => 1,
"intra-Allgather" => 1,
"intra-Scatter" => 1,
"intra-Alltoall" => 1,
"intra-Gatherv" => 1,
"intra-Allgatherv" => 1,
"intra-Scatterv" => 1,
"intra-Alltoallv" => 1,
"intra-Allreduce" => 1,
"intra-Reduce" => 1,
"intra-Scan" => 1,
"intra-Exscan" => 1,
"intra-Reduce_scatter" => 1,
"intra-Bcast" => 1,
);
# Additional special cases
# "comm-Recv" => 1, (before status)
# "comm-Sendrecv" , "comm->Sendrecv_replace"
# "dtype-Pack", "dtype-Unpack",
while (<>) {
s/#.*//g;
if (!/\S/) { next; }
if (/<(\w*)>/) {
print $_;
next;
}
$isStatic = "";
$isConst = "";
if (/static/) {
s/static\s*//;
$isStatic="static ";
}
s/MPI:://g;
if (/const\s*$/) {
s/const\s*$//;
$isConst = " const";
}
if (/([\w:]*)\s+(\w*)::(\w*)\((.*)\)/) {
$returnType = $1;
$class = $2;
$routine = $3;
$args = $4;
}
elsif (/([\w:]*)\s+(\w*)\((.*)\)/) {
$returnType = $1;
$class = "base";
$routine = $2;
$args = $3;
}
else {
print STDERR "Cannot categorize $_";
}
# Check for routines to skip because they are special
if (defined($SkipRoutines{"$class-$routine"})) {
next;
}
$origArgs = $args;
# Check for a duplicate defnition with no Status
if (defined($KnownRoutines{"$class-$routine"})) {
$oldargs = $KnownRoutines{"$class-$routine"};
if ( ($oldargs =~ /Status/) && ! ($args =~ /Status/) ) {
# Skip this entry (handled automatically by buildiface)
next;
}
else {
print STDERR "$class-$routine has multiple definitions\n";
print STDERR "First: $routine($oldargs)\n";
print STDERR "Second: $routine($args)\n";
next;
}
}
$KnownRoutines{"$class-$routine"} = $origArgs;
# Clean out the args
$cleanargs = "";
# remove the last ), and make it either a , or a blank.
# the rule in the following is that args end in a ,
$args =~ s/\)//;
if ($args =~ /\S/) { $args = $args . ","; }
# Split into single args to match entire argument
foreach $arg (split(/,/,$args)) {
$argConst = 0;
$arg =~ s/^\s*//;
$arg =~ s/\s*$//g;
if ($arg =~ /^const\s/) {
$argConst = 1;
$arg =~ s/^const\s*//g;
}
$arg =~ s/^int\s+\w*$//g;
$arg =~ s/^Aint\s+\w*$//g;
$arg =~ s/^int\s+\w*\s*\[\]\s*//g;
$arg =~ s/^Aint\s+\w*\s*\[\]\s*//g;
$arg =~ s/^int\s*&\s*\w*$/in:refint/g;
$arg =~ s/^Aint\s*&\s*\w*$//g; # Hope that the automatic
# handling of * -> & works
$arg =~ s/^Offset\s*&\s*\w*$//g; # Ditto for offset
$arg =~ s/^Offset\s+\w*//g;
$arg =~ s/Prequest\s+\w*\[\]\s*/in:preqarray:1/;
$arg =~ s/Request\s+\w*\[\]\s*/in:reqarray:1/;
$arg =~ s/Status\s+\w*\[\]\s*/out:statusarray:1/;
$arg =~ s/bool\s+\w*\[\]\s*/in:boolarray:-2/;
$arg =~ s/^Status\s*&\s*\w*//g; # Status handled by buildiface
$arg =~ s/void\s*\*\s*\w*//g;
$arg =~ s/char\s*\*\s*\w*//g;
$arg =~ s/Datatype\s+\w*\[\]/in:dtypearray:--count--/g;
$arg =~ s/^bool\s+\w*/in:bool/g;
$arg =~ s///g;
if ($argConst) {
if ($arg =~ /\s/) {
if ($arg =~ /(\w*)\s*&\s*\w*/) {
$arg = "in:constref:$1";
}
else {
if ($arg =~ /dtypearray/) {
$arg =~ s/dtypearray/dtypeconstarray/;
}
else {
$arg = "in:const-$arg";
}
}
}
else {
$arg = "in:const";
}
}
$cleanargs .= "$arg ,";
}
# ALL args are terminated by a ,. Thus,
# in the case of a single arg, there is a ,
# NO args is empty.
$args = $cleanargs;
# Most MPI functions have the class as the first arg:
if ($isStatic eq "" && $class ne "base") {
$fnchash = "$class-$routine";
if (defined($FuncHasClassAtEnd{$fnchash})) {
$args .= ",";
}
else {
$args = "," . $args;
}
}
# Most MPI functions that return an object in a class do so at the end
if ($returnType ne "void" && $returnType ne "bool") {
$args .= "return,";
}
# Trim off the last comma
$args =~ s/,\s*$//;
if (!defined($ShortClassName{$class})) {
print STDERR "$class has no short name\n";
}
$sclass = $ShortClassName{$class};
print "$sclass-$routine $isStatic$returnType ($args)$isConst\n";
}