#!/usr/local/bin/perl
require 5.001;

# format_comment
#
#     written by bill bumgarner in response to lo's hacquage.  send
# bugs, suggestions, etc. to <bbum@friday.com>
#
# Attempts to intelligently format a c-style comment based on whatever
#     it finds on stdin.  NOTE:  This is NOT for use as a code
#     commentor... it will do evil things to code.
#
#   Features:
#
# - auto wraps to $lineLength characters per line.
# - indents all comments based on indention of first line
# - can re-format existing c comments
# - if the first line contains /*, the characters following the '/*' but
#     not including any random text will be used to determine the format
#     of the comment
# - /*- will create a comment with a row of ----'s at the beginning/end
# - /*= same, but with =====
# - /*+ same, but with +++++
# - /*" surround comment with /*" and "*/ for use with autodoc
# - "" same as above
# - /** create double bullets down left side
# - /*** triple bullets
# - // line left side w/'//'
# - /***= triple bullets w/ =========== at begin/end.
#
#   BUGS:
#
# Not intelligent about the end of the input stream-- if one makes
# a selection in C land, and repeatedly runs this script on the
# selection, the length of the comment will grow by one line each
# time.

BEGIN {
    use Getopt::Long;

    ##  version & authorship info
    $file_version      = '$Revision: 1.6 $';
    $file_id	       = '$Id: format_comment,v 1.6 1995/07/17 23:00:47 bbum Exp $';
    $file_copyright    = 
	'Friday Software & Consulting, 1995 All Rights Reserved';
    $file_author       = '<bbum@friday.com>';
     push (@file_contributors,
	   'K. Lo Shih <lo@scissor.com>');

    ## post process id and version
    $file_id	  =~ s!(\$\w+: |\$)!!g;
    $file_version =~ s!(\$\w+: |\$)!!g;

    $show_usage = "unrecognized or invalid argument"
	unless &GetOptions('lib=s@',
			   'tab=i',
			   'version',
			   'help'
			   );

    ## bogus stuff to shut up -w
    $opt_help	 = $opt_help if $opt_help;
    $opt_version = $opt_version if $opt_version;
    $opt_tab	 = $opt_tab if $opt_tab;

    unshift (@INC, @opt_lib)
	if @opt_lib;
}

&usage ($show_usage)
    if $show_usage;

&usage
    if $opt_help;

&show_version
    if $opt_version;

$lineLength = 75;

if ($opt_tab) {
  $tabSize    = $opt_tab;
} else {
  $tabSize = 8;
}

$tabs	    = " " x $tabSize;

$: = "\n\t ";

# goto first non-blank line
while (<STDIN>) {
    s!\t!$tabs!g;
    last
	if m!\S!;
}

# find indention and prefix
$process = $_;
if ($process =~ m!^(\s*)(.*)!) {
    $space   = $1;
    $process = $2;
} else {
    $space = '';
}


# set prefix and mode (and retrieve end-o-first line)
if ($process =~ m!^\s*""(.*)!) {
    $prefix = '*';
    $mode   = '"';
    $out    = $1;
} elsif ($process =~ m!^\s*/([/*]+)(.*)!) { 
    $prefix = $1;
    $process = $2;
    if ( $process =~ m!(["-=+]*)\s*(.*)!) { ## "
	$mode   = substr $1, 0, 1;
	$out    = $2;
    } else {
	if ($process =~ m!(\s*)(.*)!) {
	    $space  .= $1;
	    $out     = $2;
	} else {
	    $out = '';
	}
    }	
} else {
    $prefix = '*';
    $mode   = '';
    $out    = $process;
}

if ($prefix =~ m!^/!) {
    $pLength = length $prefix;
    $prefix = '/' x (($pLength > 1) ? $pLength : 2);
    $doSurround = 0;
} else {
    $prefix = '*' x (length $prefix);
    $doSurround = 1;
}

if ((length $prefix) > 1) {
    $hPrefix = '*' x ((length $prefix) - 1);
} else {
    $hPrefix = $prefix;
}

$indentLen = (length $space) + 1;
if ($indentLen) {
    $hIndent = " " x ($indentLen - 1);
    # adjust indent according to width of prefix.
    if( (length $prefix) > 1) {
	$indent = $hIndent;
    } else {
	$indent = " " x ($indentLen);
    }
} else {
    $indent = ((length $prefix) > 1) ? "" : " ";
    $hIndent = "";
}

## build line header
$lineHead = "$indent$prefix ";
$outLength = ($lineLength - (length $lineHead));

# set up mode
if($mode eq '"') { ## "
   $autodoc = 1;
   $mode = '';
} else {
    $mode = $mode x $outLength;
}

# spew opener and mode line
if ($doSurround) {
    if ($autodoc) {
	# autodoc only deals w/a single * between the / and the " ## "
	print "$hIndent/*\"\n"; ## "
    } else {
	if ($mode) {
	    print "$hIndent/$hPrefix $mode\n";
	} else {
	    print "$hIndent/$hPrefix\n";
	}
    }
}

format CODE_TOP =
.

# dynamically build format
$format  = "format CODE_OUT = \n$lineHead^" .
    '<' x  ($outLength - 1) . "~~\n" .
    '$out' . "\n.\n";
eval $format;
die $@ if $@;

# set page length to [near] infinite (and set up formats)
$- = 100000000;
$~ = CODE_OUT;
$^ = CODE_TOP;

$out =~ s!(\S+)\s*$!$1 !;

# grab stuff from first line.
$blankLineCount = 0;
while(<STDIN>) {
    # remove whitespace and any '*'s from beginning of line
    s!^\s*"?[*/]*\s*!!; ## "
    s!\t!$tabs!g;

    unless(length) {
	# empty line -- flush $out
	write;
	$out = '';
	$blankLineCount++;
    } else {
	# line w/stuff -- concatenate to last line.
	for(;$blankLineCount != 0;$blankLineCount--) {
	    print "$lineHead\n";
	}
	$out .= $_;
    }
}

write
    if ($out =~ m!\S+!);

# spew close
if ($doSurround) {
    if ($autodoc) {
        print "$hIndent\"*/\n";
    } else {
        print "$indent$prefix $mode\n"
	    if defined($mode);
        print "$indent$hPrefix/\n";
    }
}

sub usage {
    $error_fmt = shift;
    
    $0 = substr $0, (rindex $0, '/')+1;
    
    select(STDERR);
    
    printf "$0: $error_fmt\n", @_
	if $error_fmt;

    print <<_ENDOFUSAGE_;
Usage: $0 [-version] [-help]

   -version	     Display version/copyright and development information.
   -help             Show this help and exit.	   
_ENDOFUSAGE_
    exit(1);
}

sub show_version
{
    $0 = substr $0, (rindex $0, '/')+1;
    print "This is $0 v$file_version\n";
    print "Copyright $file_copyright\n";
    print "Please send bugs and suggestions to:";
    print "$file_author\n";
    print "Improvements by:\n\t";
    print join("\n\t", @file_contributors), "\n";
    exit(0);
}
