#!/bin/sh 
 
lines=`cat $0 | wc -l` 
lines=`expr $lines - 14` 
tail -$lines $0 > /tmp/runperl$$ 
echo "# $0 $*" >> /tmp/runperl$$ 
while [ $# -ne 0 ] 
do 
    line=$1 
    shift 
    totline="$totline\`$line" 
done 
exec perl /tmp/runperl$$ $0 $totline 
 
unlink($0); 
 
sub strippath 
{ 
    local($fullname) = @_; 
 
    $fullname =~ m|^(.*/)?([^/]*)$|; 
    ($path,$file) = ($1,$2); 
    return($file,$path); 
} 
 
($0) = &strippath(shift); 
 
$args = "@ARGV"; 
$args =~ s/^.//; 
@ARGV = split('\`',$args); 
 
# Written by: Sean Ahern (ahern@llnl.gov) 
# 
# this is a reimplementation, as a filter, of the vile paragraph reformatter. 
# 
# USAGE:  reformat [-w width] [-c] [prefix] 
# It reads stdin and outputs a reformatted paragraph on stdout. 
# 
# The vile macro I use to run this is: 
# 
# ; Format a paragraph 
# 1 store-macro 
#     set-variable %savcol $curcol 
#     set-variable %savline $curline 
#     ~if &equal $char &ascii ">" 
#         set-variable %pre @"Prefix string: " 
#     ~else 
#         set-variable %pre "" 
#     ~endif 
#     ~force filter-til forward-paragraph &cat "reformat -w78 " %pre 
#     ~force %savline goto-line 
#     ~force %savcol goto-column 
# ~endm 
# bind-key execute-macro-1 ^P 
# 
# It does the standard stuff of filtering a paragraph, but it will also prompt 
# you for a prefix string if your cursor is on a ">".  I probably should put in 
# math to calculate the width from the wrapmargin or the fill-col, rather than 
# hardcoding "78", but I'll leave that as an exercise for the reader. 
 
require("getopt.pl"); 
 
$debug = 0; 
print "Debugging messages turned on.\n" if ($debug == 1); 
 
$endings = "'\\\"\\\`\\)\\]}";   # Extra slashes because this string is used in 
                                 # regular expressions. 
 
# Get the width.  If none specified, default to 72. 
$opt_w = 72; 
$opt_c = 0; 
&Getopt("w:"); 
$save_width = $opt_w; 
&Getopt("c"); 
 
# If we have an argument, use it, otherwise "". 
if (scalar(@ARGV) >= 1) 
{ 
    $name = shift(@ARGV); 
} else 
{ 
    $name = ""; 
} 
 
# Get the indents from a line.  If there is a special character sequence (#, 
# >, *, or /*) then return that sequence and the second indent.  Otherwise 
# just return the first indent and nothing for the characters and second 
# indent. 
sub get_indent 
{ 
    local($line) = @_; 
    local(@ret); 
 
    # Process tabs into spaces 
    $line =~ s/\t/        /g; 
 
    $ret[0] = ""; 
    $ret[1] = ""; 
    $ret[2] = ""; 
 
    # if there is a special character at the front of the line... 
    $pattern = "[#>\*]+|/\*|//" if ($opt_c != 1); 
    $pattern = "[#>]+" if ($opt_c == 1); 
    if (($opt_c != 1) && ($line =~ m=^\s*([#>\*]+|/\*|//)=)) 
    { 
        $line =~ m=^(\s*)([#\*]+|/\*|//|(\s*>)+)(\s*)=; 
        $ret[0] = $1; 
        $ret[1] = $2; 
        $ret[2] = $4; 
    } elsif (($opt_c == 1) && ($line =~ m=^\s*([#>]+)=)) 
    { 
        $line =~ m=^(\s*)(#+|(\s*>)+)(\s*)=; 
        $ret[0] = $1; 
        $ret[1] = $2; 
        $ret[2] = $4; 
    } else 
    { 
        $line =~ m=^(\s*)=; 
        $ret[0] = $1; 
    } 
 
    return(@ret); 
} 
 
sub check_for_C_comment 
{ 
    # If we have a "/*" indent, change it to be " *". 
    if ($indent_characters eq "/\*") 
    { 
        $C_comment = 1; 
        $indent_characters = " *"; 
 
        # If we don't have a second indent 1, make one. 
        if (length($second_indent[1]) == 0) 
        { 
            $second_indent[1] = " "; 
        } 
    } 
 
    if ($indent_characters eq "//") 
    { 
        $C_comment = 1; 
    } 
} 
 
sub line_break 
{ 
    print "Breaking line...\n" if ($debug == 1); 
 
    # Print out the line so far, after processing. 
    $output_line =~ s/\s*$//; 
    print "Output: \"$output_line\"\n" if ($debug == 1); 
    print "$output_line\n"; 
 
    # Reset the line. 
    $output_line = ""; 
    $length = 0; 
    $width = $save_width; 
 
    &check_for_C_comment(); 
 
    # If we don't have an indent, preserve the second indent level. 
    $output_line .= "$second_indent[0]$indent_characters$second_indent[1]"; 
    $length += length($second_indent[0])+ 
               length($indent_characters)+ 
               length($second_indent[1]); 
 
    # We don't care if the last word was "etc.". 
    $etc_pending = 0; 
} 
 
$have_name = 0 if ($name =~ /^\s*$/); 
$have_name = 1 if ($name !~ /^\s*$/); 
 
# At the start, we haven't printed anything out. 
$etc_pending = 0; 
$length = 0; 
$printed_word = 0; 
$indent_characters = ""; 
$old_indent_characters = ""; 
$C_comment = 0; 
$output_line = ""; 
 
# Read in all of the input 
@lines = <STDIN>; 
 
# Check to see if we already have something of the form "name>" on the first 
# line. 
if ($lines[0] =~ /^\s*(\w+)>/) 
{ 
    $name = $1; 
    $have_name = 1; 
    for($i=0;$i<scalar(@lines);$i++) 
    { 
        $lines[$i] =~ s/$name>/>/; 
    } 
} 
 
# Process the first line for spaces and indents. 
($first_indent[0],$indent_characters,$first_indent[1]) = &get_indent($lines[0]); 
print "First indent 0: \"$first_indent[0]\"\n" if ($debug == 1); 
print "First indent 1: \"$first_indent[1]\"\n" if ($debug == 1); 
 
if ($indent_characters !~ /^\s*$/) 
{ 
    print "We have an indent of \"$indent_characters\".\n" if ($debug == 1); 
    $have_indent = 1; 
} else 
{ 
    $have_indent = 0; 
} 
 
# If we do have a name set up the indent to be a ">". 
if ($have_name == 1) 
{ 
    $old_indent_characters = $indent_characters; 
    $indent_characters = ">"; 
    $indent_characters = "$name$indent_characters"; 
    $have_indent = 1; 
} 
 
# Set up the width for use on the first line.  We'll reset it for later 
# lines. 
$width = $save_width; 
 
# Adjust the width to accomodate the indent and the spaces. 
$save_width -= length($indent_characters); 
 
# If we have more than one line... 
if (scalar(@lines) > 1) 
{ 
    # Process the second line for spaces. 
    ($second_indent[0],$foobar,$second_indent[1]) = &get_indent($lines[1]); 
    $second_indent[0] .= " " if (length($foobar) == 1); 
    $second_indent[0] .= "  " if (length($foobar) == 2); 
    $foobar = ""; 
} else 
{ 
    $second_indent[0] = $first_indent[0]; 
    $second_indent[1] = $first_indent[1]; 
} 
 
# If we have a newline for the second indent, use the first indent. 
$second_indent[0] = $first_indent[0] if ($second_indent[0] =~ /\n/); 
$second_indent[1] = $first_indent[1] if ($second_indent[1] =~ /\n/); 
 
print "Second indent 0: \"$second_indent[0]\"\n" if ($debug == 1); 
print "Second indent 1: \"$second_indent[1]\"\n" if ($debug == 1); 
 
# If we have a newline for the first indent, just use the second indent. 
$first_indent[0] = $second_indent[0] if ($first_indent[0] =~ /\n/); 
$first_indent[1] = $second_indent[1] if ($first_indent[1] =~ /\n/); 
 
if (length($indent_characters) != 0) 
{ 
    # Adjust the first indent if we have less of an indent on the second 
    # line. 
    if (length($first_indent[0]) > length($second_indent[0])) 
    { 
        $first_indent[1] = substr($first_indent[0],length($second_indent[0])); 
        $first_indent[0] = $second_indent[0]; 
    } 
 
    # Adjust the second indent. 
    if (length($second_indent[0]) >= 
        (length($first_indent[0]) + 
         length($indent_characters) - 
         length($name) 
        ) 
       ) 
    { 
        $test = substr($second_indent[0], 
                                   length($first_indent[0])+ 
                                   length($indent_characters)- 
                                   length($name)); 
        if (length($test) != 0) 
        { 
            $second_indent[1] = $test; 
        } 
    } 
 
    $second_indent[0] = $first_indent[0]; 
} 
 
# Print the indent for the first line.  It's different from the rest, most 
# likely. 
if ($have_indent == 1) 
{ 
    $output_line .= "$first_indent[0]$indent_characters$first_indent[1]"; 
    $length = length($first_indent[0])+length($indent_characters)+ 
              length($first_indent[1]); 
} else 
{ 
    $output_line .= "$first_indent[0]"; 
    $length = length($first_indent[0]); 
} 
 
# Here we go 
$wordsave = ""; 
for($count = 0; defined($lines[$count]); $count++) 
{ 
    $_ = $lines[$count]; 
 
    # Get rid of the $indent_characters if they exist at the front of the 
    # string. 
    if ($have_indent == 1) 
    { 
        if ($have_name == 1) 
        { 
            s/^\s*($old_indent_characters ?)*\s*//; 
        } else 
        { 
            if (($C_comment == 0) || (! m|^\s*\*/|)) 
            { 
                $temp_indent = $indent_characters; 
                $temp_indent =~ s/\*/\\\*/; 
                $temp_indent =~ s/^\s*//; 
                s/^\s*($temp_indent ?)*\s*//; 
            } 
        } 
    } 
 
    # Get rid of any excess white space in all cases. 
    s/^\s*//; 
    s/\s*$//; 
 
    # Split the line into words by whitespace or split it by commas if $opt_c 
    # is specified. 
    $first_word_on_stdin_line = 1; 
    print "Processing line: \"$_\"\n" if ($debug == 1); 
    if ($opt_c == 1) 
    { 
        print "Splitting on commas.\n" if ($debug == 1); 
        @words = split(/([^,]*,)\s*/) if ($opt_c); 
    } else 
    { 
        print "Splitting on whitespace.\n" if ($debug == 1); 
        @words = split(/\s+/) if (!$opt_c); 
    } 
    for $word (@words) 
    { 
        next if ($word =~ /^\s*$/); 
        $word = "$wordsave $word" 
            if (($first_word_on_stdin_line == 1) && ($wordsave !~ /^\s*$/)); 
 
        print "Checking \"$word\"\n" if ($debug == 1); 
 
        # If printing out the current word would push us over the $width, do 
        # a line break. 
        if ($length+length($word) > $width) 
        { 
            &line_break(); 
        } 
 
        # If the last word was "etc.", we may or may not have an end of the 
        # sentence.  Check to see if the word is capitalized.  If it is, 
        # output another space.  If not, don't. 
        if (($etc_pending == 1) && ($word =~ /^[A-Z]/)) 
        { 
            $output_line .= " "; 
        } 
 
        # Add the current word to the output_line.  If we're breaking by 
        # commas, we save the word for the next line if it doesn't end in a 
        # comma. 
        if (($opt_c == 1) && ($word !~ /,$/)) 
        { 
            print "Saving \"$word\" for the next line.\n" if ($debug == 1); 
            $wordsave = $word; 
            $wordsave =~ s/^\s+//; 
            $wordsave =~ s/\s+$//; 
        } else 
        { 
            $wordsave = ""; 
            $output_line .= "$word "; 
            $length += length($word)+1; 
            $printed_word = 1; 
            $etc_pending = 0; 
        } 
 
        # If the word ends in a period, question mark, or exclamation point, 
        # we might be ending a sentence.  Check for common abbreviations to 
        # see.  If we *are* ending a sentence, we need to add another space 
        # to the output.  We also might be right after a colon. 
        if ($word =~ /[\.\?!:][$endings]*$/) 
        { 
            # Check for standard abbs. 
            if ( ($word !~ /\bMr\.[$endings]*$/) && 
                 ($word !~ /\bDr\.[$endings]*$/) && 
                 ($word !~ /\bMrs\.[$endings]*$/) && 
                 ($word !~ /\bProf\.[$endings]*$/) && 
                 ($word !~ /\bMs\.[$endings]*$/) && 
                 ($word !~ /\bSt\.[$endings]*$/) && 
                 ($word !~ /\bCo\.[$endings]*$/) && 
                 ($word !~ /\bLtd\.[$endings]*$/) && 
                 ($word !~ /\bltd\.[$endings]*$/) && 
                 ($word !~ /\bp\.m\.[$endings]*$/) && 
                 ($word !~ /\bP\.M\.[$endings]*$/) && 
                 ($word !~ /\ba\.m\.[$endings]*$/) && 
                 ($word !~ /\bA\.M\.[$endings]*$/) && 
                 ($word !~ /\bi\.e\.[$endings]*$/) && 
                 ($word !~ /\bvs\.[$endings]*$/) && 
                 ($word !~ /\bi\.e\.[$endings]*$/) && 
                 ($word !~ /\be\.g\.[$endings]*$/) && 
                 ($word !~ /\bInc\.[$endings]*$/) && 
                 ($word !~ /\bU\.S\.[$endings]*$/) && 
                 ($word !~ /\bJan\.[$endings]*$/) && 
                 ($word !~ /\bFeb\.[$endings]*$/) && 
                 ($word !~ /\bMar\.[$endings]*$/) && 
                 ($word !~ /\bApr\.[$endings]*$/) && 
                 ($word !~ /\bJun\.[$endings]*$/) && 
                 ($word !~ /\bJul\.[$endings]*$/) && 
                 ($word !~ /\bAug\.[$endings]*$/) && 
                 ($word !~ /\bSep\.[$endings]*$/) && 
                 ($word !~ /\bSept\.[$endings]*$/) && 
                 ($word !~ /\bOct\.[$endings]*$/) && 
                 ($word !~ /\bNov\.[$endings]*$/) && 
                 ($word !~ /\bU\.S\.[$endings]*$/) && 
                 ($word !~ /\bBldg\.[$endings]*$/) && 
                 ($word !~ /\bDec\.[$endings]*$/) 
               ) 
            { 
                # Strange case here.  "etc." sometimes sends a sentence and 
                # sometimes not.  Check the next letter to see if it's 
                # capitallized. 
                if ($word =~ /\betc\.[$endings]*$/) 
                { 
                    $etc_pending = 1; 
                } else 
                { 
                    # No special cases, add another space to send the 
                    # sentence. 
                    $output_line .= " "; 
                    $length++; 
                } 
            } 
        } 
        $first_word_on_stdin_line = 0; 
    } 
 
    # At the end of the first line, we have to check for a C comment. 
    &check_for_C_comment(); 
 
    # If we got to the end of the first input line without printing anything, 
    # do a line break. 
    if ($printed_word == 0) 
    { 
        &line_break(); 
    } 
} 
 
# Print out the last line, after processing. 
print "Outputting final line.\n" if ($debug == 1); 
$output_line .= "$wordsave" if ($wordsave !~ /^\s*$/); 
$output_line =~ s/\s*$//; 
print "$output_line\n"; 
