#!/usr/local/bin/perl
#
# Copyright (C) 1995 Friday Software & Consulting
# Usage and redistribution is subject to the MiscKit license.

require 5.001;

# CHANGELOG:
#
# $Log: format_comment,v $
# Revision 1.2  1995/09/27  18:44:53  bbum
# Tried to fix '#' formatting.  Failed.  Fixed other minor things.
#
# Revision 1.1  1995/09/26  22:44:23  bbum
# Created
#
# Revision 1.2  1995/09/21  18:11:17  bbum
# Fixed hash character indention
#
# Revision 1.1  1995/09/21  17:57:27  bbum
# Added support for '#' comments.
#
# Revision 1.6  1995/07/17  23:00:47  bbum
# Now handles things like '//' in middle of text.
# Fixed first-character-offset-by-one on re-formats of '/*' style comments.
#
# Revision 1.5  1995/07/17  22:48:11  bbum
# [Finally] fixed the damn end o' line spacing creep.
# Added RCS ChangeLog support.
#

# 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 the 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.2 $';
    $file_id	     = '$Id: format_comment,v 1.2 1995/09/27 18:44:53 bbum Exp $';
  $file_copyright    = 
	'Friday Software & Consulting, 1995 All Rights Reserved';
  $file_author       = '<bbum@friday.com>';
  push (@file_contributors,
		'K. Lo Shih <lo@apdg.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@',
					   'version',
					   'help'
					  );
  
  ## bogus stuff to shut up -w
  $opt_help	  = $opt_help if $opt_help;
  $opt_version  = $opt_version if $opt_version;
  
  unshift (@INC, @opt_lib)
	if @opt_lib;
}

&usage ($show_usage)
if $show_usage;

&usage
  if $opt_help;

&show_version
  if $opt_version;

$lineLength = 75;
$tabSize    = 4;
$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*""(.*)!) {
  # autodoc comment...
  $prefix = '*';
  $mode   = '"';
  $out    = $1;
} elsif ($process =~ m!^\s*(/([/*]+)|([\#]+))(.*)!) {
  $prefix  = $2 ? $2 : $3;
  $process = $4;
  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;
} elsif ($prefix =~ m!^\#!) {
  $prefix = '#' x length $prefix;
  $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;

# Hack fix; adjust for '#' mode
if ($prefix =~ m!^\#! && (length $prefix) == 1) {
	$indentLen--;
}

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 is constructed by concatenating the
# $lineHead with the appropriate number of '<' charcters followed by a ~~
# such that the format automatically wraps the contents of the line...

$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
  if ($prefix =~ m!^\#!) {
    s!^\s*[\#]*\s*!!;
  }
  else {
    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 $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);
}
