#! /usr/bin/env perl # (Tested with -w; 2/23/07) # # Find the parse.sub routine. use warnings; my $maintdir = "maint"; my $rootdir = "."; if ( ! -s "maint/parse.sub" ) { my $program = $0; $program =~ s/extractparms//; if (-s "$program/parse.sub") { $maintdir = $program; $rootdir = $program; $rootdir =~ s/\/maint//g; print "Rootdir = $rootdir\n" if $debug; } } require "$maintdir/parse.sub"; $debug = 0; $showfiles = 0; $quiet = 0; $wwwFormat = 1; $wwwFullpage = 1; # params has key "name" and value envname:filename:description %params = (); # Strict is used to control checking of error message strings. $gStrict = 0; if (defined($ENV{"DEBUG_STRICT"})) { $gStrict = 1; } # Check for special args @files = (); %skipFiles = (); $outfile = ""; foreach $arg (@ARGV) { if ($arg =~ /^-showfiles/) { $showfiles = 1; } elsif( $arg =~ /-debug/) { $debug = 1; } elsif( $arg =~ /-quiet/) { $quiet = 1; } elsif( $arg =~ /-outfile=(.*)/) { $outfile = $1; } elsif( $arg =~ /-strict/) { $gStrict = 1; } elsif( $arg =~ /-skip=(.*)/) { $skipFiles{$1} = 1; } else { print "Adding $arg to files\n" if $debug; if (-d $arg) { # Add all .c files from directory $arg to the list of files # to process (this lets us shorten the arg list) @files = (@files, &ExpandDir( $arg )); } else { $files[$#files+1] = $arg; } } } # End of argument processing # Setup the basic file for errnames - Now determined in ExpandDirs #@errnameFiles = ( "$rootdir/src/mpi/errhan/errnames.txt" ); if ($outfile ne "") { $OUTFD = "MyOutFile"; open( $OUTFD, ">$outfile" ) or die "Could not open $outfile\n"; } else { $OUTFD = STDOUT; } # Setup before processing the files # Process the definitions foreach $file (@files) { print "$file\n" if $showfiles; &ProcessFile( $file ); } # Create the output files from the input that we're read if ($wwwFormat) { &OutputWebpage; } #----------------------------------------------------------------------------- # ROUTINES # ---------------------------------------------------------------------------- # ========================================================================== # Call this for each file # This reads a C source or header file and adds does the following: # $filename = ""; # Make global so that other routines can echo filename sub ProcessFile { # Leave filename global for AddTest $filename = $_[0]; my $linecount = 0; open (FD, "<$filename" ) or die "Could not open $filename\n"; while () { $linecount++; # Next, remove any comments $_ = StripComments( FD, $_ ); # Skip the definition of the function if (/int\s+MPIU_Param_/) { $remainder = ""; next; } # Match the known routines and macros. # MPIU_Param_register( const char name[], const char envname[], # const char description[] ) %KnownErrRoutines = ( 'MPIU_Param_register' => '0:1:2', ); while (/(MPIU_Param_[a-z0-9_]+)\s*(\(.*)$/) { my $routineName = $1; my $arglist = $2; if (!defined($KnownErrRoutines{$routineName})) { print "Skipping $routineName\n" if $debug; last; } print "Found $routineName\n" if $debug; my ($nameArgLoc,$envnameArgLoc,$descripArgLoc) = split(/:/,$KnownErrRoutines{$routineName}); ($leader, $remainder, @args ) = &GetSubArgs( FD, $arglist ); # Discard leader if ($debug) { print "Line begins with $leader\n"; # Use $leader to keep -w happy foreach $arg (@args) { print "|$arg|\n"; } } # Process the signature # if signature does not match new function prototype, then skip it if ($#args < $descripArgLoc) { if (!defined($bad_syntax_in_file{$filename})) { $bad_syntax_in_file{$filename} = 1; print STDERR "Warning: $routineName call with too few arguments in $filename\n"; } next; } my $name = $args[$nameArgLoc]; my $envname = $args[$envnameArgLoc]; my $descrip = $args[$descripArgLoc]; $name =~ s/^\"//; $name =~ s/\"$//; $envname =~ s/^\"//; $envname =~ s/\"$//; $descrip =~ s/^\"//; $descrip =~ s/\"$//; $params{$name} = "$envname:$filename:$descrip"; # Temp for debugging #print STDOUT "$name\t$envname\t$descrip\n"; } continue { $_ = $remainder; } } close FD; } # Get all of the .c files from the named directory, including any subdirs # Also, add any errnames.txt files to the errnamesFiles arrays sub ExpandDir { my $dir = $_[0]; my @otherdirs = (); my @files = (); opendir DIR, "$dir"; while ($filename = readdir DIR) { if ($filename =~ /^\./ || $filename eq ".svn") { next; } elsif (-d "$dir/$filename") { $otherdirs[$#otherdirs+1] = "$dir/$filename"; } elsif ($filename =~ /(.*\.[chi])$/) { # Test for both Unix- and Windows-style directory separators if (!defined($skipFiles{"$dir/$filename"}) && !defined($skipFiles{"$dir\\$filename"})) { $files[$#files + 1] = "$dir/$filename"; } } elsif ($filename eq "errnames.txt") { $errnameFiles[$#errnameFiles+1] = "$dir/$filename"; } } closedir DIR; # (almost) tail recurse on otherdirs (we've closed the directory handle, # so we don't need to worry about it anymore) foreach $dir (@otherdirs) { @files = (@files, &ExpandDir( $dir ) ); } return @files; } sub OutputWebpage { if ($wwwFullpage) { print $OUTFD "\n\nParameters for MPICH2\n"; print $OUTFD "\n

Parameters for MPICH2

\r\n"; } &OutputWebbody; if ($wwwFullpage) { print $OUTFD "\n\r\n"; } } sub OutputWebbody { print $OUTFD "
\n"; foreach my $key (sort(keys(%params))) { my ($envname, $filename, $descript); if ($params{$key} =~ /^([^:]*):([^:]*):(.*)/) { $envname = $1; $filename = $2; $descript = $3; print STDOUT "
$key ($envname)\n
$descript\n"; } } print $OUTFD "
\n"; }