Blame maint/extracterrmsgs

Packit Service c5cf8c
#! /usr/bin/env perl
Packit Service c5cf8c
# (Tested with -w; 10/5/04)
Packit Service c5cf8c
# 
Packit Service c5cf8c
# Find the parse.sub routine.
Packit Service c5cf8c
my $maintdir = "./maint";
Packit Service c5cf8c
my $rootdir  = ".";
Packit Service c5cf8c
if ( ! -s "maint/parse.sub" ) {
Packit Service c5cf8c
    my $program = $0;
Packit Service c5cf8c
    $program =~ s/extracterrmsgs//;
Packit Service c5cf8c
    if (-s "$program/parse.sub") {
Packit Service c5cf8c
	$maintdir = $program;
Packit Service c5cf8c
	$rootdir  = $program;
Packit Service c5cf8c
	$rootdir  =~ s/\/maint//g;
Packit Service c5cf8c
	print "Rootdir = $rootdir\n" if $debug;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
require "$maintdir/parse.sub";
Packit Service c5cf8c
Packit Service c5cf8c
$debug = 0;
Packit Service c5cf8c
$careful = 0;        # Set careful to 1 to flag unused messages
Packit Service c5cf8c
$carefulFilename = "";
Packit Service c5cf8c
$showfiles = 0;
Packit Service c5cf8c
$quiet = 0;
Packit Service c5cf8c
$build_test_pgm = 1;
Packit Service c5cf8c
# FIXME: checkErrClass should be set to 1; currently set to zero
Packit Service c5cf8c
# to permit autogen.sh to complete
Packit Service c5cf8c
$checkErrClass = 1;
Packit Service c5cf8c
Packit Service c5cf8c
# Strict is used to control checking of error message strings.
Packit Service c5cf8c
$gStrict = 0;
Packit Service c5cf8c
if (defined($ENV{"DEBUG_STRICT"})) { $gStrict = 1; }
Packit Service c5cf8c
Packit Service c5cf8c
# Check for special args
Packit Service c5cf8c
@files = ();
Packit Service c5cf8c
%skipFiles = ();
Packit Service c5cf8c
my @errnameFiles = ();
Packit Service c5cf8c
$outfile = "";
Packit Service c5cf8c
foreach $arg (@ARGV) {
Packit Service c5cf8c
    if ($arg =~ /^--?showfiles/) { $showfiles = 1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?debug/) { $debug = 1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?quiet/) { $quiet = 1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?notest/) { $build_test_pgm = 0; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?outfile=(.*)/) { $outfile = $1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?careful=(.*)/) {
Packit Service c5cf8c
	$careful = 1;
Packit Service c5cf8c
	$carefulFilename = $1;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif( $arg =~ /^--?careful/) { $careful = 1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?strict/)  { $gStrict = 1; }
Packit Service c5cf8c
    elsif( $arg =~ /^--?skip=(.*)/) { $skipFiles{$1} = 1; }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	print "Adding $arg to files\n" if $debug;
Packit Service c5cf8c
	if (-d $arg) {
Packit Service c5cf8c
	    # Add all .c files from directory $arg to the list of files 
Packit Service c5cf8c
	    # to process (this lets us shorten the arg list)
Packit Service c5cf8c
	    @files = (@files, &ExpandDir( $arg ));
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
            # errname files are treated differently
Packit Service c5cf8c
            if ($arg =~ m{(^|[/\\])errnames.txt$}) {
Packit Service c5cf8c
                push @errnameFiles, $arg;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            else {
Packit Service c5cf8c
                $files[$#files+1] = $arg;
Packit Service c5cf8c
            }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
# End of argument processing
Packit Service c5cf8c
Packit Service c5cf8c
# Setup the basic file for errnames - Now determined in ExpandDirs
Packit Service c5cf8c
#@errnameFiles = ( "$rootdir/src/mpi/errhan/errnames.txt" );
Packit Service c5cf8c
Packit Service c5cf8c
if ($outfile ne "") {
Packit Service c5cf8c
    $OUTFD = "MyOutFile";
Packit Service c5cf8c
    open( $OUTFD, ">$outfile" ) or die "Could not open $outfile\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
else {
Packit Service c5cf8c
    $OUTFD = STDOUT;
Packit Service c5cf8c
}
Packit Service c5cf8c
# Setup before processing the files
Packit Service c5cf8c
if ($build_test_pgm && -d "test/mpi/errhan") {
Packit Service c5cf8c
    # Get current directory incase we need it for the error message
Packit Service c5cf8c
    my $curdir = `pwd`;
Packit Service c5cf8c
    open( TESTFD, ">test/mpi/errhan/errcode.c" ) or die "Cannot create test program errcode.c in $curdir/test/mpi/errhan\n";
Packit Service c5cf8c
    print TESTFD "/* -*- Mode: C++; c-basic-offset:4 ; -*- */\
Packit Service c5cf8c
/*  \
Packit Service c5cf8c
 *  (C) 2004 by Argonne National Laboratory.\
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.\
Packit Service c5cf8c
 *\
Packit Service c5cf8c
 * This file is automatically generated by maint/extracterrmsgs\
Packit Service c5cf8c
 * DO NOT EDIT\
Packit Service c5cf8c
 */\n";
Packit Service c5cf8c
    print TESTFD "#include <stdio.h>\n#include <stdlib.h>\n#include \"mpi.h\"\n";
Packit Service c5cf8c
    print TESTFD "#define MPIR_ERR_FATAL 1\n";
Packit Service c5cf8c
    print TESTFD "#define MPIR_ERR_RECOVERABLE 0\n";
Packit Service c5cf8c
    print TESTFD "int MPIR_Err_create_code( int, int, char *, int, int, const char [], const char [], ... );\n";
Packit Service c5cf8c
    print TESTFD "void ChkMsg( int, int, const char [] );\n\n";
Packit Service c5cf8c
    print TESTFD "int main(int argc, char **argv)\n";
Packit Service c5cf8c
    print TESTFD "{\n    int err;\n    MPI_Init( 0, 0 );\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Process the definitions
Packit Service c5cf8c
foreach $file (@files) {
Packit Service c5cf8c
    print "$file\n" if $showfiles;
Packit Service c5cf8c
    &ProcessFile( $file );
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#
Packit Service c5cf8c
# Create the hash %longnames that maps the short names to the long names,
Packit Service c5cf8c
# $longnames{shortname} => longname, by reading the errnames.txt files
Packit Service c5cf8c
foreach my $sourcefile (@errnameFiles) {
Packit Service c5cf8c
    #print STDERR "processing $sourcefile for error names\n";
Packit Service c5cf8c
    &ReadErrnamesFile( $sourcefile );
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Create the output files from the input that we've read
Packit Service c5cf8c
&CreateErrmsgsHeader( $OUTFD );
Packit Service c5cf8c
&CreateErrMsgMapping( $OUTFD );
Packit Service c5cf8c
Packit Service c5cf8c
if ($build_test_pgm && -d "test/mpi/errhan") {
Packit Service c5cf8c
    print TESTFD "    MPI_Finalize();\n    return 0;\n}\n";
Packit Service c5cf8c
    close TESTFD;
Packit Service c5cf8c
}    
Packit Service c5cf8c
Packit Service c5cf8c
#
Packit Service c5cf8c
# Generate a list of unused keys
Packit Service c5cf8c
if ($careful) {
Packit Service c5cf8c
    my $OUTFD = STDERR;
Packit Service c5cf8c
    if ($carefulFilename ne "") {
Packit Service c5cf8c
	$OUTFD = "ERRFD";
Packit Service c5cf8c
	open $OUTFD, ">$carefulFilename" or die "Cannot open $carefulFilename";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    foreach $shortname (keys(%longnames)) {
Packit Service c5cf8c
	if (!defined($longnamesUsed{$shortname}) ||
Packit Service c5cf8c
	    $longnamesUsed{$shortname} < 1) {
Packit Service c5cf8c
	    $loc = $longnamesDefined{$shortname};
Packit Service c5cf8c
	    print $OUTFD "Name $shortname is defined in $loc but never used\n";
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($carefulFilename ne "") {
Packit Service c5cf8c
	close $OUTFD;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#-----------------------------------------------------------------------------
Packit Service c5cf8c
# ROUTINES
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
# From the data collected above, generate the file containing the error message
Packit Service c5cf8c
# text.
Packit Service c5cf8c
# This is a temporary routine; the exact output form will be defined later
Packit Service c5cf8c
sub CreateErrmsgsHeader {
Packit Service c5cf8c
    $FD = $_[0];
Packit Service c5cf8c
    print $FD "/* -*- Mode: C; c-basic-offset:4 ; -*- */\
Packit Service c5cf8c
/*  \
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.\
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.\
Packit Service c5cf8c
 *\
Packit Service c5cf8c
 * This file automatically created by extracterrmsgs\
Packit Service c5cf8c
 * DO NOT EDIT\
Packit Service c5cf8c
 */\n";
Packit Service c5cf8c
    print $FD "#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG__CLASS
Packit Service c5cf8c
typedef struct msgpair {
Packit Service c5cf8c
        const unsigned int sentinal1;
Packit Service c5cf8c
        const char *short_name, *long_name; 
Packit Service c5cf8c
        const unsigned int sentinal2; } msgpair;
Packit Service c5cf8c
#endif\n"
Packit Service c5cf8c
}
Packit Service c5cf8c
#
Packit Service c5cf8c
# We also need a way to create the records
Packit Service c5cf8c
# We then hash these on the first occurance (or precompute the hashes?)
Packit Service c5cf8c
#
Packit Service c5cf8c
# The error messages are output in the following form:
Packit Service c5cf8c
# typedef struct {const char short[], const long[]} namemap;
Packit Service c5cf8c
# Generic messages
Packit Service c5cf8c
# static const char[] short1 = "";
Packit Service c5cf8c
# static const char[] long1 = "";
Packit Service c5cf8c
# ...
Packit Service c5cf8c
# static const namemap[] = { {short1, long1}, {...} }
Packit Service c5cf8c
#
Packit Service c5cf8c
sub CreateErrMsgMapping {
Packit Service c5cf8c
    my $OUTFD = $_[0];
Packit Service c5cf8c
Packit Service c5cf8c
    # Create a mapping of MPI error classes to the specific error
Packit Service c5cf8c
    # message by index into generic_err_msgs.  This reads the file
Packit Service c5cf8c
    # baseerrnames, looks up the generic message, and maps the MPI error
Packit Service c5cf8c
    # class to the corresponding index.
Packit Service c5cf8c
    # We must do this here because we must ensure that all MPI error
Packit Service c5cf8c
    # classes have been added to the generic messages
Packit Service c5cf8c
    @class_msgs = ();
Packit Service c5cf8c
    open (FD, "<$rootdir/src/mpi/errhan/baseerrnames.txt" ) || 
Packit Service c5cf8c
	die "Could not open $rootdir/src/mpi/errhan/baseerrnames.txt\n";
Packit Service c5cf8c
    while (<FD>) {
Packit Service c5cf8c
	s/#.*$//;
Packit Service c5cf8c
	my ($mpiname,$num,$shortmsg) = split(/\s\s*/);
Packit Service c5cf8c
	if (!defined($shortmsg)) {
Packit Service c5cf8c
	    # Incase there is no short message entry (!)
Packit Service c5cf8c
	    $shortmsg = "";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	if ($shortmsg ne "")
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    if ($shortmsg =~ /\%/)
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Warning: generic message $shortmsg in baseerrnames.txt contains format control\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    $generic_msgs{$shortmsg}++;
Packit Service c5cf8c
	    $generic_loc{$shortmsg} = ":baseerrnames.txt";
Packit Service c5cf8c
Packit Service c5cf8c
	    $class_msgs[$num] = "$shortmsg";
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close (FD);
Packit Service c5cf8c
Packit Service c5cf8c
    # For the case of classes only, output the strings for the class 
Packit Service c5cf8c
    # messages
Packit Service c5cf8c
    print $OUTFD "#if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG__CLASS\n";
Packit Service c5cf8c
    print $OUTFD "#define MPIR_MAX_ERROR_CLASS_INDEX $#class_msgs+1\n";
Packit Service c5cf8c
    print $OUTFD "static const char *classToMsg[] = {\n";
Packit Service c5cf8c
    for (my $i=0; $i<=$#class_msgs; $i++) {
Packit Service c5cf8c
	my $shortname = $class_msgs[$i];
Packit Service c5cf8c
	my $msg       = $longnames{$shortname};
Packit Service c5cf8c
	print $OUTFD "\"$msg\", /* $i  $class_msgs[$i] */\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    print $OUTFD "0 }; \n";
Packit Service c5cf8c
    print $OUTFD "#endif /* MSG_CLASS */\n";
Packit Service c5cf8c
Packit Service c5cf8c
    # Now, output each short,long key
Packit Service c5cf8c
    # Do the generic, followed by the specific, messages
Packit Service c5cf8c
    # The long messages must be available for the generic message output.
Packit Service c5cf8c
    # An alternative is to separate the short from the long messages;
Packit Service c5cf8c
    # the long messages are needed for > MSG_NONE, the short for > MSG_CLASS.
Packit Service c5cf8c
    print $OUTFD "#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG__CLASS\n";
Packit Service c5cf8c
    print $OUTFD "/* The names are in sorted order, allowing the use of a simple\
Packit Service c5cf8c
  linear search or bisection algorithm to find the message corresponding to\
Packit Service c5cf8c
  a particular message */\n";
Packit Service c5cf8c
    my $num = 0;
Packit Service c5cf8c
    foreach my $key (sort keys %generic_msgs)
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$longvalue = "\"\0\"";
Packit Service c5cf8c
	if (!defined($longnames{$key}))
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    $seenfile = $generic_loc{$key};
Packit Service c5cf8c
	    if ($key =~ /^\*\*/) {
Packit Service c5cf8c
		# If the message begins with text, assume that it is a 
Packit Service c5cf8c
		# litteral message
Packit Service c5cf8c
		print STDERR "Shortname $key for generic messages has no expansion (first seen in file $seenfile)\n";
Packit Service c5cf8c
		print STDERR "(Add expansion to $sourcefile)\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
	    # Keep track of which messages we have seen
Packit Service c5cf8c
	    $longnamesUsed{$key} += 1;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	
Packit Service c5cf8c
	# Escape any naked quotes (This should be applied somewhere else?)
Packit Service c5cf8c
#	$longvalue = s/(?
Packit Service c5cf8c
Packit Service c5cf8c
	$longvalue = "\"" . $longnames{$key} . "\"";
Packit Service c5cf8c
Packit Service c5cf8c
	print $OUTFD "static const char short_gen$num\[\] = \"$key\";\n";
Packit Service c5cf8c
#	print $OUTFD "static const char short_gen$num\[\] = $key;\n";
Packit Service c5cf8c
	print $OUTFD "static const char long_gen$num\[\]  = $longvalue;\n";
Packit Service c5cf8c
	# Remember the number assigned to this short string.
Packit Service c5cf8c
	$short_to_num{$key} = $num;
Packit Service c5cf8c
	$num ++;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    # Generate the mapping of short to long names
Packit Service c5cf8c
    print $OUTFD "\nstatic const int generic_msgs_len = $num;\n";
Packit Service c5cf8c
Packit Service c5cf8c
    # The sentinals should be hardcoded into the source file that
Packit Service c5cf8c
    # uses this file to ensure that the sentinal tests are ok.
Packit Service c5cf8c
    my $sentinal1 = "0xacebad03";
Packit Service c5cf8c
    my $sentinal2 = "0xcb0bfa11";
Packit Service c5cf8c
    print $OUTFD "static const msgpair generic_err_msgs[] = {\n";
Packit Service c5cf8c
    for (my $i = 0; $i < $num; $i ++) {
Packit Service c5cf8c
	print $OUTFD "{ $sentinal1, short_gen$i, long_gen$i, $sentinal2 }";
Packit Service c5cf8c
	print $OUTFD "," if ($i < $num - 1);
Packit Service c5cf8c
	print $OUTFD "\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    print $OUTFD "};\n";
Packit Service c5cf8c
    print $OUTFD "#endif\n\n";
Packit Service c5cf8c
Packit Service c5cf8c
    $num = 0;
Packit Service c5cf8c
    # Now output the instance specific messages
Packit Service c5cf8c
    print $OUTFD "#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG__GENERIC\n";
Packit Service c5cf8c
    foreach $key (sort keys %specific_msgs)
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$longvalue = "\"\0\"";
Packit Service c5cf8c
Packit Service c5cf8c
	if (!defined($longnames{$key}))
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    print STDERR "Shortname $key for specific messages has no expansion (first seen in file $specific_loc{$key})\n";
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
	    # Keep track of which messages we have seen
Packit Service c5cf8c
	    $longnamesUsed{$key} += 1;
Packit Service c5cf8c
	}
Packit Service c5cf8c
Packit Service c5cf8c
	# Escape any naked quotes
Packit Service c5cf8c
	$longvalue =~ s/(?
Packit Service c5cf8c
	$longvalue = "\"" . $longnames{$key} . "\"";
Packit Service c5cf8c
Packit Service c5cf8c
	print $OUTFD "static const char short_spc$num\[\] = \"$key\";\n";
Packit Service c5cf8c
#	print $OUTFD "static const char short_spc$num\[\] = $key;\n";
Packit Service c5cf8c
	print $OUTFD "static const char long_spc$num\[\]  = $longvalue;\n";
Packit Service c5cf8c
	$num ++;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    # Generate the mapping of short to long names
Packit Service c5cf8c
Packit Service c5cf8c
    print $OUTFD "\nstatic const int specific_msgs_len = $num;\n";
Packit Service c5cf8c
    print $OUTFD "static const msgpair specific_err_msgs[] = {\n";
Packit Service c5cf8c
    for (my $i = 0; $i < $num ; $i ++) {
Packit Service c5cf8c
	print $OUTFD "{ $sentinal1, short_spc$i, long_spc$i, $sentinal2 }";
Packit Service c5cf8c
	print $OUTFD "," if ($i < $num - 1);
Packit Service c5cf8c
	print $OUTFD "\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    print $OUTFD "};\n";
Packit Service c5cf8c
    print $OUTFD "#endif\n\n";
Packit Service c5cf8c
Packit Service c5cf8c
    print $OUTFD "#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG__CLASS\n";
Packit Service c5cf8c
    $maxval = $#class_msgs + 1;
Packit Service c5cf8c
    print $OUTFD "#define MPIR_MAX_ERROR_CLASS_INDEX $maxval\n";
Packit Service c5cf8c
    print $OUTFD "static int class_to_index[] = {\n";
Packit Service c5cf8c
    for (my $i=0; $i<=$#class_msgs; $i++) {
Packit Service c5cf8c
	print $OUTFD "$short_to_num{$class_msgs[$i]}";
Packit Service c5cf8c
	print $OUTFD "," if ($i < $#class_msgs);
Packit Service c5cf8c
	print $OUTFD "\n" if !(($i + 1) % 10);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    print $OUTFD "};\n";
Packit Service c5cf8c
    print $OUTFD "#endif\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
#
Packit Service c5cf8c
# Add a call to test this message for the error message.
Packit Service c5cf8c
# Handle both the generic and specific messages
Packit Service c5cf8c
#
Packit Service c5cf8c
sub AddTestCall {
Packit Service c5cf8c
Packit Service c5cf8c
    my $genericArgLoc = $_[0];
Packit Service c5cf8c
    
Packit Service c5cf8c
    my $last_errcode = "MPI_SUCCESS";  # $_[0];
Packit Service c5cf8c
    my $fatal_flag   = "MPIR_ERR_RECOVERABLE"; # $_[1];
Packit Service c5cf8c
    my $fcname       = "unknown"; # $_[2];
Packit Service c5cf8c
    my $linenum      = "__LINE__"; # $_[3];
Packit Service c5cf8c
    my $errclass     = "MPI_ERR_OTHER"; # $_[4];
Packit Service c5cf8c
Packit Service c5cf8c
    my $generic_msg = $_[$genericArgLoc+1];
Packit Service c5cf8c
    my $specific_msg = $_[$genericArgLoc+2];
Packit Service c5cf8c
    if ($#_ < $genericArgLoc+2) { $specific_msg = "0"; }
Packit Service c5cf8c
Packit Service c5cf8c
    # Ensure that the last_errcode, class and fatal flag are specified.  There are a few places where these are variables.
Packit Service c5cf8c
    if (!($last_errcode =~ /MPI_ERR_/) )
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$last_errcode = "MPI_SUCCESS";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (!($errclass =~ /MPI_ERR_/) )
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$errclass = "MPI_ERR_OTHER";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (!($fatal_flag =~ /MPIR_ERR_FATAL/) && !($fatal_flag =~ /MPIR_ERR_RECOVERABLE/))
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$fatal_flag = "MPIR_ERR_FATAL";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Generic message (first instance only)
Packit Service c5cf8c
    if (!defined($test_generic_msg{$generic_msg}))
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$test_generic_msg{$generic_msg} = $filename;
Packit Service c5cf8c
Packit Service c5cf8c
	print TESTFD "    /* $filename */\n";
Packit Service c5cf8c
	print TESTFD "    err = MPIR_Err_create_code($last_errcode, $fatal_flag, \"errcode::main\", __LINE__, $errclass, ". 
Packit Service c5cf8c
	    "$generic_msg, 0);\n";
Packit Service c5cf8c
	print TESTFD "    ChkMsg( err, $errclass, $generic_msg );\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Specific messages
Packit Service c5cf8c
    $specific_msg = "0" if ($specific_msg =~ /^\s*NULL\s*$/);
Packit Service c5cf8c
    if ($specific_msg ne "0" && !defined($test_specific_msg{$specific_msg}))
Packit Service c5cf8c
    {
Packit Service c5cf8c
	$test_specific_msg{$specific_msg} = $filename;
Packit Service c5cf8c
Packit Service c5cf8c
	print TESTFD "    {\n";
Packit Service c5cf8c
	print TESTFD "    /* $filename */\n";
Packit Service c5cf8c
	# Use types in the string to create the types with default
Packit Service c5cf8c
	# values
Packit Service c5cf8c
	my $format = $specific_msg;
Packit Service c5cf8c
	my $fullformat = $format;
Packit Service c5cf8c
	my $narg = 0;
Packit Service c5cf8c
	my @args = ();
Packit Service c5cf8c
	while ($format =~ /[^%]*%(.)(.*)/)
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    my $type = $1; 
Packit Service c5cf8c
	    $format  = $2;
Packit Service c5cf8c
	    $narg ++;
Packit Service c5cf8c
	    if ($type eq "d")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = $narg;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
            elsif ($type eq "x")
Packit Service c5cf8c
            {
Packit Service c5cf8c
                print TESTFD "    int i$narg = $narg;\n";
Packit Service c5cf8c
                $args[$#args+1] = "i$narg";
Packit Service c5cf8c
            }
Packit Service c5cf8c
	    elsif ($type eq "L") 
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    long long i$narg = $narg;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
            elsif ($type eq "X")
Packit Service c5cf8c
            {
Packit Service c5cf8c
                print TESTFD "    long long i$narg = $narg;\n";
Packit Service c5cf8c
                $args[$#args+1] = "i$narg";
Packit Service c5cf8c
            }
Packit Service c5cf8c
	    elsif ($type eq "i")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = $narg;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "t")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = $narg;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "s")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    char s$narg\[\] = \"string$narg\";\n";
Packit Service c5cf8c
		$args[$#args+1] = "s$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "p")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    char s$narg\[\] = \"pointer$narg\";\n";
Packit Service c5cf8c
		$args[$#args+1] = "s$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "C")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_COMM_WORLD;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "I")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_INFO_NULL;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "D")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_INT;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "F")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		# This must be an MPI_File since that type may not
Packit Service c5cf8c
		# be an integer (it is a pointer at this time)
Packit Service c5cf8c
		print TESTFD "    MPI_File i$narg = MPI_FILE_NULL;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "W")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_WIN_NULL;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "A")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = $narg;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "G")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_GROUP_NULL;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "O")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_SUM;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "R")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_REQUEST_NULL;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($type eq "E")
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print TESTFD "    int i$narg = MPI_ERRORS_RETURN;\n";
Packit Service c5cf8c
		$args[$#args+1] = "i$narg";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
            elsif ($type eq "c")
Packit Service c5cf8c
            {
Packit Service c5cf8c
                print TESTFD "    MPI_Count i$narg = $narg;\n";
Packit Service c5cf8c
                $args[$#args+1] = "i$narg";
Packit Service c5cf8c
            }
Packit Service c5cf8c
	    else
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Unrecognized format type $type for $fullformat in $filename\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}   
Packit Service c5cf8c
	$actargs = $#_ - $genericArgLoc - 2;
Packit Service c5cf8c
	if ($actargs != $narg)
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    print STDERR "Error: Format $fullformat provides $narg arguments but call has $actargs in $filename\n";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	print TESTFD "     err = MPIR_Err_create_code($last_errcode, $fatal_flag, \"errcode::main\", __LINE__, $errclass, " .
Packit Service c5cf8c
	    "$generic_msg, $specific_msg";
Packit Service c5cf8c
	foreach my $arg (@args) 
Packit Service c5cf8c
	{
Packit Service c5cf8c
	    print TESTFD ", $arg";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	print TESTFD " );\n";
Packit Service c5cf8c
	print TESTFD "    ChkMsg( err, $errclass, $specific_msg );\n    }\n";
Packit Service c5cf8c
	# ToDo: pass another string to ChkMsg that contains the 
Packit Service c5cf8c
	# names of the variables, as a single string (comma separated).
Packit Service c5cf8c
	# This allows us to review the source of the values for the args.
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# ==========================================================================
Packit Service c5cf8c
# Read an errnames file.  This allows us to distribute the errnames.txt
Packit Service c5cf8c
# files in the relevant modules, rather than making them part of one
Packit Service c5cf8c
# single master file.
Packit Service c5cf8c
# This updates the global hashs longnames and longnamesDefined
Packit Service c5cf8c
#  ReadErrnamesFile( filename )
Packit Service c5cf8c
# ==========================================================================
Packit Service c5cf8c
sub ReadErrnamesFile {
Packit Service c5cf8c
    my $sourcefile = $_[0];
Packit Service c5cf8c
Packit Service c5cf8c
    open( FD, "<$sourcefile" ) or return 0;
Packit Service c5cf8c
    my $linecount = 0;
Packit Service c5cf8c
    while (<FD>) {
Packit Service c5cf8c
	$linecount++;
Packit Service c5cf8c
	# Skip Comments
Packit Service c5cf8c
	if (/^\s*\#/) { next; }
Packit Service c5cf8c
	# Read entire error message (allow \ at end of line to continue)
Packit Service c5cf8c
	if (/^\s*(\*\*[^:]*):(.*)$/) {
Packit Service c5cf8c
	    my $name = $1;
Packit Service c5cf8c
	    my $repl = $2;
Packit Service c5cf8c
	    $repl =~ s/\r*\n*$//g;
Packit Service c5cf8c
	    while ($repl =~ /\\\s*$/) {
Packit Service c5cf8c
		# If there is a \\ at the end, read another.  
Packit Service c5cf8c
		# Remove the \ at the end (an alternative is to turn
Packit Service c5cf8c
		# it into a \n (newline), but we may want to avoid 
Packit Service c5cf8c
		# multiline messages
Packit Service c5cf8c
		$repl =~ s/\\\s*$//;
Packit Service c5cf8c
		my $inline = <FD>;
Packit Service c5cf8c
		$linecount++;
Packit Service c5cf8c
		$inline =~ s/^\s*//;   # remove leading spaces
Packit Service c5cf8c
		$repl .= $inline;
Packit Service c5cf8c
		$repl =~ s/[\r\n]*$//g; # remove newlines
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    # Check that the name and the replacement text at least
Packit Service c5cf8c
	    # partially match as to format specifiers
Packit Service c5cf8c
	    # (They should have exactly the same pattern, i.e., 
Packit Service c5cf8c
	    # if the name has %d %x in is, the replacement should 
Packit Service c5cf8c
	    # have %d %x, in that order)
Packit Service c5cf8c
	    my $namehasformat = ($name =~ /%/);
Packit Service c5cf8c
	    my $replhasformat = ($repl =~ /%/);
Packit Service c5cf8c
	    if ($namehasformat != $replhasformat) {
Packit Service c5cf8c
		print STDERR "Warning: format control usage in $name and $repl do not agree in $sourcefile\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
#	    if (!defined($longnames{"\"$name\""}))
Packit Service c5cf8c
#	    {
Packit Service c5cf8c
#		$longnames{"\"$name\""} = $repl;
Packit Service c5cf8c
#		$longnamesDefined{"\"$name\""} = "$sourcefile:$linecount";
Packit Service c5cf8c
#	    }
Packit Service c5cf8c
	    # Check that the replacement text doesn't include a unquoted
Packit Service c5cf8c
	    # double quote
Packit Service c5cf8c
	    if ($repl =~ /(.)\"/) {
Packit Service c5cf8c
		my $prechar = $1;
Packit Service c5cf8c
		if ($1 ne "\\") {
Packit Service c5cf8c
		    print STDERR "Warning: Replacement text for $name contains an unescaped double quote: $repl\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if (!defined($longnames{$name}))
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		$longnames{$name} = $repl;
Packit Service c5cf8c
		$longnamesDefined{$name} = "$sourcefile:$linecount";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    else
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Warning: attempt to redefine $name.  Duplicate ignored.\n";
Packit Service c5cf8c
		print STDERR "Previously defined at $longnamesDefined{$name} with value \"$longnames{$name}\"\n";
Packit Service c5cf8c
		print STDERR "Redefined at $sourcefile:$linecount with value \"$repl\"\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close( FD );
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# ==========================================================================
Packit Service c5cf8c
# Call this for each file
Packit Service c5cf8c
# This reads a C source or header file and adds does the following:
Packit Service c5cf8c
#   adds any generic message short names encountered to the hash generic_msgs.
Packit Service c5cf8c
#   adds any specific message short names encounter to the hash specific_msgs.
Packit Service c5cf8c
#   adds the filename to the hash generic_loc{msg} as the value (: separated)
Packit Service c5cf8c
#       and the same for hash specific_loc{msg}.
Packit Service c5cf8c
#   The last two are used to provide better error reporting.
Packit Service c5cf8c
#
Packit Service c5cf8c
$filename = "";    # Make global so that other routines can echo filename
Packit Service c5cf8c
sub ProcessFile
Packit Service c5cf8c
{ 
Packit Service c5cf8c
    # Leave filename global for AddTest
Packit Service c5cf8c
    $filename = $_[0];
Packit Service c5cf8c
    my $linecount = 0;
Packit Service c5cf8c
    open (FD, "<$filename" ) or die "Could not open $filename\n";
Packit Service c5cf8c
Packit Service c5cf8c
    while (<FD>) {
Packit Service c5cf8c
	$linecount++;
Packit Service c5cf8c
	# Skip code that is marked as ignore (e.g., for
Packit Service c5cf8c
	# macros that are used to simplify the use of MPIR_Err_create_code
Packit Service c5cf8c
	# (such macros must also be recognized and processed)
Packit Service c5cf8c
	if (/\/\*\s+--BEGIN ERROR MACROS--\s+\*\//) {
Packit Service c5cf8c
	    while (<FD>) {
Packit Service c5cf8c
		$linecount++;
Packit Service c5cf8c
		if (/\/\*\s+--END ERROR MACROS--\s+\*\//) { last; }
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    $remainder = "";
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	# Next, remove any comments
Packit Service c5cf8c
	$_ = StripComments( FD, $_ );
Packit Service c5cf8c
	# Skip the definition of the function
Packit Service c5cf8c
	if (/int\s+MPI[OUR]_Err_create_code/) { $remainder = ""; next; }
Packit Service c5cf8c
	# Match the known routines and macros.
Packit Service c5cf8c
	# Then check that the arguments match if there is a 
Packit Service c5cf8c
	# specific string (number of args matches the number present)
Packit Service c5cf8c
        # MPIR_ERR_CHK(FATAL)?ANDJUMP[1-4]?(cond,code,class,gmsg[,smsg,args])
Packit Service c5cf8c
        # MPIR_ERR_SET(FATAL)?ANDJUMP[1-4]?(code,class,gmsg[,smsg,args])
Packit Service c5cf8c
	# MPIR_ERR_CHK(FATAL)?ANDSTMT[1-4]?(cond,code,class,stmt,gmsg[,smsg,args])
Packit Service c5cf8c
	# MPIR_ERR_SET(FATAL)?ANDSTMT[1-4]?(code,class,stmt,gmsg[,smsg,args])
Packit Service c5cf8c
	# Value is a tuple of:
Packit Service c5cf8c
	#  the count of args where the generic msg begins (starting from 0)
Packit Service c5cf8c
	#  location of __LINE__ (-1 for none)
Packit Service c5cf8c
	#  specific msg arg required (0 for no, > 0 for yes)
Packit Service c5cf8c
	#  is the generic message an indirect from errnames.txt (1=yes 0=no)
Packit Service c5cf8c
	#  location of the error class
Packit Service c5cf8c
	%KnownErrRoutines = ( 'MPIR_Err_create_code'      => '5:3:1:1:4', 
Packit Service c5cf8c
			      'MPIO_Err_create_code'      => '5:3:1:0:-1', 
Packit Service c5cf8c
			      'MPIR_ERR_SET'              => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETSIMPLE'        => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SET1'             => '2:-1:1:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SET2'             => '2:-1:2:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETANDSTMT'       => '3:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETANDSTMT1'      => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDSTMT2'      => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDSTMT3'      => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDSTMT4'      => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDJUMP'       => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETANDJUMP1'      => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDJUMP2'      => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDJUMP3'      => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETANDJUMP4'      => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDSTMT'       => '4:-1:0:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDSTMT1'      => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDSTMT2'      => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDSTMT3'      => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDSTMT4'      => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDJUMP'       => '3:-1:0:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDJUMP1'      => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDJUMP2'      => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDJUMP3'      => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKANDJUMP4'      => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATAL'         => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALSIMPLE'   => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATAL1'        => '2:-1:1:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATAL2'        => '2:-1:2:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDSTMT'  => '3:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDSTMT1' => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDSTMT2' => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDSTMT3' => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDSTMT4' => '3:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDJUMP'  => '2:-1:0:1:1',
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDJUMP1' => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDJUMP2' => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDJUMP3' => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_SETFATALANDJUMP4' => '2:-1:1:1:1', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDSTMT'  => '4:-1:0:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDSTMT1' => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDSTMT2' => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDSTMT3' => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDSTMT4' => '4:-1:1:1:2', 
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDJUMP'  => '3:-1:0:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDJUMP1' => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDJUMP2' => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDJUMP3' => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERR_CHKFATALANDJUMP4' => '3:-1:1:1:2',
Packit Service c5cf8c
			      'MPIR_ERRTEST_VALID_HANDLE' => '4:-1:0:1:3',
Packit Service c5cf8c
			      );
Packit Service c5cf8c
	while (/(MPI[OUR]_E[A-Za-z0-9_]+)\s*(\(.*)$/) {
Packit Service c5cf8c
	    my $routineName = $1;
Packit Service c5cf8c
	    my $arglist     = $2;
Packit Service c5cf8c
	    if (!defined($KnownErrRoutines{$routineName})) {
Packit Service c5cf8c
		print "Skipping $routineName\n" if $debug;
Packit Service c5cf8c
		last;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    print "Found $routineName\n" if $debug;
Packit Service c5cf8c
	    my ($genericArgLoc,$hasLine,$hasSpecific,$onlyIndirect,$errClassLoc) = 
Packit Service c5cf8c
		split(/:/,$KnownErrRoutines{$routineName});
Packit Service c5cf8c
Packit Service c5cf8c
	    ($leader, $remainder, @args ) = &GetSubArgs( FD, $arglist );
Packit Service c5cf8c
	    # Discard leader 
Packit Service c5cf8c
	    if ($debug) {
Packit Service c5cf8c
		print "Line begins with $leader\n";   # Use $leader to keep -w happy
Packit Service c5cf8c
		foreach $arg (@args) {
Packit Service c5cf8c
		    print "|$arg|\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    # Process the signature
Packit Service c5cf8c
	    
Packit Service c5cf8c
	    # if signature does not match new function prototype, then skip it
Packit Service c5cf8c
	    if ($#args < $genericArgLoc) {
Packit Service c5cf8c
		if (!defined($bad_syntax_in_file{$filename})) {
Packit Service c5cf8c
		    $bad_syntax_in_file{$filename} = 1;
Packit Service c5cf8c
		    print STDERR "Warning: $routineName call with too few arguments in $filename\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
		next;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($hasLine >= 0 && 
Packit Service c5cf8c
		($args[$hasLine] ne "__LINE__" && $args[$hasLine] ne "line")) {
Packit Service c5cf8c
		if (!defined($bad_syntax_in_file{$filename})) {
Packit Service c5cf8c
		    $bad_syntax_in_file{$filename} = 1;
Packit Service c5cf8c
		    my $tmpi = $hasLine + 1;
Packit Service c5cf8c
		    print STDERR "Warning: Expected __LINE__ or line as ${tmpi}th argument of $routineName in $filename\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
		next;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($errClassLoc >= 0 && $checkErrClass) {
Packit Service c5cf8c
		if (!($args[$errClassLoc] =~ /^MPI_ERR_/)  &&
Packit Service c5cf8c
		    !($args[$errClassLoc] =~ /^MPI_T_ERR_/) &&
Packit Service c5cf8c
		    !($args[$errClassLoc] =~ /^MPIDI_CH3I_SOCK_ERR_/) &&
Packit Service c5cf8c
		    !($args[$errClassLoc] =~ /^MPIX_ERR_/) &&
Packit Service c5cf8c
		    !($args[$errClassLoc] =~ /^errclass/) &&
Packit Service c5cf8c
                    !($args[$errClassLoc] =~ /^\*\(errflag_\)/) &&
Packit Service c5cf8c
                    !($args[$errClassLoc] =~ /^\*errflag/)) {
Packit Service c5cf8c
		    $bad_syntax_in_file{$filename} = 1;
Packit Service c5cf8c
		    print STDERR "Invalid argument $args[$errClassLoc] for the MPI Error class in $routineName in $filename\n";
Packit Service c5cf8c
		    next;
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    
Packit Service c5cf8c
	    #my $last_errcode = $args[0];
Packit Service c5cf8c
	    #my $fatal_flag = $args[1];
Packit Service c5cf8c
	    #my $fcname = $args[2];
Packit Service c5cf8c
	    #my $linenum = $args[3];
Packit Service c5cf8c
	    #my $errclass = $args[4];
Packit Service c5cf8c
	    my $generic_msg = $args[$genericArgLoc];
Packit Service c5cf8c
	    my $specific_msg = "0";
Packit Service c5cf8c
	    if ($hasSpecific) {
Packit Service c5cf8c
		$specific_msg = $args[$genericArgLoc+1];
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    # Check the generic and specific message arguments
Packit Service c5cf8c
	    if ($generic_msg =~ /\s$/)
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Warning: trailing blank on arg $generic_msg in $filename!\n"; 
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($onlyIndirect && !($generic_msg =~ /^\"\*\*\S+\"$/)) {
Packit Service c5cf8c
Packit Service c5cf8c
		print STDERR "Error: generic message $generic_msg has incorrect format in $filename\n";
Packit Service c5cf8c
		next;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($generic_msg =~ /%/) {
Packit Service c5cf8c
		print STDERR "Warning: generic message $generic_msg in $filename contains a format control\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
		 
Packit Service c5cf8c
	    $specific_msg = "0" if ($specific_msg =~ /^\s*NULL\s*$/);
Packit Service c5cf8c
	    if ($specific_msg =~ /^[1-9]/)
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Error: instance specific message $specific_msg in $filename is an invalid integer ". 
Packit Service c5cf8c
		    "(must be 0 or a string)\n";
Packit Service c5cf8c
		next;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($specific_msg eq $generic_msg)
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Warning: generic and instance specific messages must be different " .
Packit Service c5cf8c
		    "(file $filename, message $generic_msg)\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($specific_msg ne "0" && !($specific_msg =~ /\%/))
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		print STDERR "Warning: instance specific message $specific_msg in $filename contains no format control\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($specific_msg =~ /%/) {
Packit Service c5cf8c
		# Specific message includes format values.  Check
Packit Service c5cf8c
		# for number and for valid strings if %s
Packit Service c5cf8c
		my $nargs = 0;
Packit Service c5cf8c
		my $tmpmsg = $specific_msg;
Packit Service c5cf8c
		my @stringLocs = ();
Packit Service c5cf8c
		while ($tmpmsg =~ /[^%]*%(.)(.*)/) {
Packit Service c5cf8c
		    $tmpmsg = $2;
Packit Service c5cf8c
		    my $followchar = $1;
Packit Service c5cf8c
		    if ($followchar eq "s") {
Packit Service c5cf8c
			$stringLocs[$#stringLocs+1] = $nargs;
Packit Service c5cf8c
		    }
Packit Service c5cf8c
		    if ($followchar ne "%") {
Packit Service c5cf8c
			$nargs ++;
Packit Service c5cf8c
		    }
Packit Service c5cf8c
                    if (! ($followchar =~ /[%sdxitpcDCRWOEIGFALX]/) ) {
Packit Service c5cf8c
			print STDERR "Warning: Unrecognized format specifier in specific message $specific_msg in $filename\n";
Packit Service c5cf8c
		    }
Packit Service c5cf8c
		}
Packit Service c5cf8c
		if ($nargs != $#args - $genericArgLoc - 1) {
Packit Service c5cf8c
		    my $actargs = $#args - $genericArgLoc - 1;
Packit Service c5cf8c
		    print STDERR "Warning: wrong number of arguments for instance specific message $specific_msg in $filename; expected $nargs but found $actargs\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($#stringLocs >= 0 && $gStrict) {
Packit Service c5cf8c
		    # Check for reasonable strings if strict checking requested
Packit Service c5cf8c
		    for (my $i=0; $i<=$#stringLocs; $i++) {
Packit Service c5cf8c
			my $index = $stringLocs[$i];
Packit Service c5cf8c
			my $string = $args[$genericArgLoc+2+$index];
Packit Service c5cf8c
			if ($string =~ /\"/) {
Packit Service c5cf8c
			    # Allow a few special cases:
Packit Service c5cf8c
			    # Always: all uppercase and _, single word
Packit Service c5cf8c
			    my $stringOk = 0;
Packit Service c5cf8c
			    if ($string =~ /^\"[A-Z_]*\"$/) {
Packit Service c5cf8c
				$stringOk = 1;
Packit Service c5cf8c
			    }
Packit Service c5cf8c
			    elsif ($string =~ /^\"\w*\"$/) {
Packit Service c5cf8c
				if (1) { $stringOk = 1; }
Packit Service c5cf8c
			    }
Packit Service c5cf8c
			    if (!$stringOk) {
Packit Service c5cf8c
				print STDERR "Warning: explicit string as argument to specific message $specific_msg in $filename; explicit string is $string\n";
Packit Service c5cf8c
			    }
Packit Service c5cf8c
			}
Packit Service c5cf8c
		    }
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    if ($build_test_pgm) {
Packit Service c5cf8c
		&AddTestCall( $genericArgLoc, @args )
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    if ($generic_msg =~ /^\"(.*)\"$/) {
Packit Service c5cf8c
		$generic_msg = $1;
Packit Service c5cf8c
		$generic_msgs{$generic_msg}++;
Packit Service c5cf8c
		$generic_loc{$generic_msg} .= ":$filename";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    else {
Packit Service c5cf8c
		$generic_msgs{$generic_msg}++;
Packit Service c5cf8c
		$generic_loc{$generic_msg} .= ":$filename";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
Packit Service c5cf8c
	    if ($specific_msg =~ /^\"(\*\*.*)\"/)
Packit Service c5cf8c
	    {
Packit Service c5cf8c
		$specific_msg = $1;
Packit Service c5cf8c
		$specific_msgs{$specific_msg}++;
Packit Service c5cf8c
		$specific_loc{$specific_msg} .= ":$filename";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	continue
Packit Service c5cf8c
        {
Packit Service c5cf8c
            $_ = $remainder;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }		
Packit Service c5cf8c
    close FD;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Get all of the .c files from the named directory, including any subdirs
Packit Service c5cf8c
# Also, add any errnames.txt files to the errnamesFiles arrays
Packit Service c5cf8c
sub ExpandDir {
Packit Service c5cf8c
    my $dir = $_[0];
Packit Service c5cf8c
    my @otherdirs = ();
Packit Service c5cf8c
    my @files = ();
Packit Service c5cf8c
    opendir DIR, "$dir";
Packit Service c5cf8c
    while ($filename = readdir DIR) {
Packit Service c5cf8c
	if ($filename =~ /^\./) {
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	elsif (-d "$dir/$filename") {
Packit Service c5cf8c
	    $otherdirs[$#otherdirs+1] = "$dir/$filename";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	elsif ($filename =~ /(.*\.[chi])(pp){0,1}$/) {
Packit Service c5cf8c
	    # Test for both Unix- and Windows-style directory separators
Packit Service c5cf8c
	    if (!defined($skipFiles{"$dir/$filename"}) &&
Packit Service c5cf8c
		!defined($skipFiles{"$dir\\$filename"})) {
Packit Service c5cf8c
		$files[$#files + 1] = "$dir/$filename";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	elsif ($filename eq "errnames.txt") {
Packit Service c5cf8c
	    $errnameFiles[$#errnameFiles+1] = "$dir/$filename";
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    closedir DIR;
Packit Service c5cf8c
    # (almost) tail recurse on otherdirs (we've closed the directory handle,
Packit Service c5cf8c
    # so we don't need to worry about it anymore)
Packit Service c5cf8c
    foreach $dir (@otherdirs) {
Packit Service c5cf8c
	@files = (@files, &ExpandDir( $dir ) );
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return @files;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#
Packit Service c5cf8c
# Other todos:
Packit Service c5cf8c
# It would be good to keep track of any .N MPI_ERR_xxx names in the structured
Packit Service c5cf8c
# comment and match these against any MPI_ERR_yyy used in the code, emitting a
Packit Service c5cf8c
# warning message for MPI_ERR_yyy values used in the code but not mentioned 
Packit Service c5cf8c
# in the header.  This could even apply to routines that are not at the MPI
Packit Service c5cf8c
# layer, forcing all routines to document all MPI error classes that they might
Packit Service c5cf8c
# return (this is like requiring routines to document the exceptions that 
Packit Service c5cf8c
# they may throw).