#!/usr/bin/perl
#
#NAME
#  mfl - makefile list munger
#
#SYNOPSIS
#   mfl [$len]
#
#DESCRIPTION
#  This little program reformats a "makefile list".  That's one of the
#  common sort of makefile entries that consists of an initial chunk
#  in column 1, followed by a list of file names.  For example:
#
#  FOO= foo.c bar.c foo.h qux.h
#  foo.o: foo.c bar.c foo.h qux.h blorch.c kumquat.c loquat.c loquat.o local.h
#
#  What this program does: It reads these lists of  file  names,  and  coughs
#  them  up  formatted  as  make  likes  to  see them.  The result will be in
#  alphabetical order, with a tab in col 1, as many file names  as  will  fit
#  into $len bytes, and a backslash on all but the last line. Blank lines are
#  ignored. If the first non-blank line is indented, its first "word" will be
#  proceeded  by  a blank line and produced on a line by itself.  This can be
#  used from vi to rewrite a file list in a neater form.
#
#  When fed the above lines (without the initial "#  " chars), the
#  result of the vi command ".,+!mfl 40" is:
#  
#  FOO= \
#      bar.c foo.c foo.h qux.h 
#  
#  foo.o: \
#      bar.c blorch.c foo.c foo.h kumquat.c \
#      local.h loquat.c loquat.o qux.h 
#
#  This program was designed to be used mostly from inside an editor like  vi
#  that  allows  using  external programs as edit commands.  The default line
#  length is 70 chars, for assorted reasons.  Note that the  resulting  lines
#  will  generally  be somewhat longer, because the algorithm is to add names
#  to the line until $len is passed.  This  is  in  part  to  guarantee  that
#  there's at least one name on each line, so that the list will terminate in
#  a finite number of lines.
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu> 1991, 1998, 2002
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$len = $ARGV[0] || 80;

# Read in the data and collect the file names.
for $line (<STDIN>) {
	$line =~ s/\s*\\+\s*/ /g;
	@line = split(/\s+/,$line);
	if ($line[0]) {
		&par() if ($name || %name);
		$name = shift(@line);
	}
	foreach $fld (@line) {
		next if !$fld;
		next if $fld eq "\\";
		$name{$fld} ++;
	}
}
&par() if ($name || %name);
exit 0;

sub par {
	$line = '';
	# If there was an initial name, produce it on a separate line.
	if ($name) {
		print "$name";	# Initially had \n at the start, but this was annoying.
		print " \\\n" if %name;
	}
	# Run thru the file names and produce all but the last line.
	if (%name) {
		for $key (sort keys %name) {
			if (length($line) + length($key) > $len) {
				print "\t$line\\\n";
				$line = '';
			}
			$line .= "$key ";
		}
	# The above guarantees at least one file name on the last line.
	print "\t$line\n";
	}
	$name = '';
	%name = ();
}
