#! /usr/bin/env perl # # File of useful routines use to process the MPI source files. This is # included by routines that process parameters and error messages, along with # tools to check for proper usage (such as system routines and preprocessor # tests). # # GetBalancedParen( FD, curline ) # Returns a balanced parenthesis string, starting at curline. Reads from FD # if necessary. Skips any comments. # Returns the pair (leading, result, remainder) # Leading is anything before the opening paren. If no opening paren in the # line, returns the current line as "leading" # Newlines are removed. sub GetBalancedParen { my $paren_count = 1; my $result = ""; my $count = 0; my $leading = ""; my $maxcount = 200; $FD = $_[0]; $curline = $_[1]; # Remove escaped newlines $curline =~ s/\\$//; if ($curline =~ /^([^\(]*)\((.*)$/) { $leading = $1; $curline = $2; $result = "("; print "Found open paren\n" if $debug; } else { $leading = $curline; return ($leading, "", "" ); } while ($count < $maxcount && $paren_count > 0) { if ($curline =~ /^([^\(\)]*\()(.*$)/) { # Found an opening paren $result .= $1; $curline = $2; $paren_count++; print "Found open paren\n" if $debug; } elsif ($curline =~ /^([^\(\)]*\))(.*$)/) { # Found a closing paren $result .= $1; $curline = $2; $paren_count--; print "Found close paren\n" if $debug; } else { # Need to read a new line $result .= $curline; $curline = <$FD>; $curline =~ s/[\r]*\n//; # Remove escaped newlines $curline =~ s/\\$//; } $count ++; } return ($leading, $result, $curline); } # Like get balanced paren, but for a string. Simpler because it does not need # to handle balanced text. sub GetString { my $result = ""; my $count = 0; my $leading = ""; my $maxcount = 200; $FD = $_[0]; $curline = $_[1]; if ($curline =~ /^([^\"]*)\"(.*)$/) { $leading = $1; $curline = $2; $result = "\""; print "Found quote\n" if $debug; } else { $leading = $curline; return ($leading, "", "" ); } while ($count < $maxcount) { if ($curline =~ /^([^\"]*\\\")(.*$)/) { # Found an escaped quote $result .= $1; $curline = $2; print "Found escaped quote\n" if $debug; } elsif ($curline =~ /^([^\"]*\")(.*$)/) { # Found the closing quote $result .= $1; $curline = $2; print "Found closing quote\n" if $debug; last; } else { # Need to read a new line $result .= $curline; $curline = <$FD>; $curline =~ s/[\r]*\n//; } $count ++; } return ($leading, $result, $curline); } # # GetSubArgs( FD, curline ) returns an array of the arguments of a routine. # Specifically, it converts (a,b,c) into an array containing "a", "b", and "c". # The special feature of this is that any commas that are within balanced # parenthesis are included within their argument. # Actually returns # (leader, remainder, (@args) ) # in this order so the last values are always all of the args # so you don't need to know sub GetSubArgs { my @args = (); my $curline; my ($outer, $leader, $remainder, $arg); $FD = $_[0]; $curline = $_[1]; # Remove any embedded newlines $curline =~ s/[\r\n]//g; $curline =~ /^\(/ || die "No initial paren"; ($leader, $outer, $remainder ) = &GetBalancedParen( $FD, $curline ); # Strip off the first and last parens # Because of the greedy algorithm, the \s before the closing paren # won't be used. To avoid problems with empty arguments, we remove # those blanks separately $outer =~ /^\s*\(\s*(.*)\s*\)\s*$/; $outer = $1; if ($outer =~ /(.*)\s+$/) { $outer = $1; } print "Line to tokenize is $outer\n" if $debug; $arg = ""; while ($outer ne "") { if ($outer =~ /^([^,\(\"]*)\s*,\s*(.*$)/) { # simple arg $arg .= $1; $args[$#args+1] = $arg; print "Found simple arg $arg (remainder $2)\n" if $debug; $outer = $2; $arg = ""; } elsif ($outer =~ /^([^,\"]*)\((.*$)/) { # arg with () ($startarg,$bal,$outer) = &GetBalancedParen( $FD, $outer ); $arg = $arg . $startarg . $bal; # Rest of code will catch the rest } elsif ($outer =~ /^([^,\(]*)\"(.*$)/) { # arg with "" ($startarg,$string,$outer) = &GetString( $FD, $outer ); print "string is $string\n" if $debug; $arg = $arg . $startarg . $string; # Rest of code will catch the rest } else { # no comma print "Adding |$outer| to arg $arg\n" if $debug; $arg .= $outer; $outer = ""; } } if ($arg ne "") { $args[$#args+1] = $arg; } print "Number of args is 1+$#args\n" if $debug; return ($leader, $remainder, @args ); } # remainder = StripComments( FD, inputline ) # removes comments from a line and returns the line. Read more if necessary # Places the comment into $comment_line; # The external "cxx_header" adds // to the comments stripped # Set a default value for cxx_header if (!defined($cxx_header)) { $cxx_header = 0; } sub StripComments { my $FD = $_[0]; my $curline = $_[1]; my $remainder = ""; $comment_line = ""; if ($cxx_header == 1 && $curline =~ /(\/\/.*)/) { $comment_line = $1; $curline =~ s/\/\/.*//; print "Removed C++ comment, now is $curline\n" if $debug; return $curline; } while ($curline =~ /\/\*/) { print "Curline = $curline\n" if $debug; if ($curline =~ /(\/\*.*?\*\/)/s) { $comment_line = $1; $curline =~ s/\/\*.*?\*\///s; print "Removed comment, now is $curline\n" if $debug; # Keep looking for comments incase the line has multiple # comments } else { # Keep collecting until we find the end of the comment if (eof($FD)) { print STDOUT "Unterminated comment found$errsrc!\n"; my $line = $curline; if ($line =~ /(.*)\n/) { $line = "$1"; } print STDOUT "Comment begins with $line\n"; return $curline; } $curline .= <$FD>; } } return $curline; } # Since this is a required package, indicate that we are successful. return 1;