use strict;
use File::Basename ();
use Getopt::Long qw(:config gnu_compat);
use IO::File;
use IO::String;
my $MyName = File::Basename::basename($0);
my $Section = '1';
my $OutputFile;
Getopt::Long::GetOptions(
's|section=s' => \$Section,
'o|output=s' => \$OutputFile,
);
die "Usage: $MyName [-o|--output outfile] [-s|--section section] executable\n" unless scalar(@ARGV) == 1;
my $output;
if(defined($OutputFile)) {
$output = IO::File->new($OutputFile, "w") or die "$MyName: Can't open $OutputFile: $!\n";
} else {
$output = IO::File->new_from_fd(fileno(STDOUT), "w") or die "$MyName: Can't duplicate STDOUT: $!\n";
}
my $cmd = $ARGV[0];
my $cmdversion = `$cmd --version`;
die "$MyName: $cmd --version failed\n" if $@;
my $cmdhelp = `$cmd --help`;
die "$MyName: $cmd --help failed\n" if $@;
$cmd = File::Basename::basename($cmd);
if(defined($ENV{HELP2MAN_CHANGE})) {
foreach my $c (split(';', $ENV{HELP2MAN_CHANGE})) {
my($from, $to) = split(',', $c, 2);
$to = '' unless defined($to);
$cmd =~ s/\b$from\b/$to/g;
$cmdversion =~ s/\b$from\b/$to/g;
$cmdhelp =~ s/\b$from\b/$to/g;
}
}
my @pg = split("\n\n", $cmdversion);
my @lines = split("\n", shift(@pg));
my $version = shift(@lines);
my $date;
if(($date = $version) =~ s/^.*\D(\d{4}-\d{2}-\d{2})(\D.*|$)/\1/) {
my @month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my($y, $m, $d) = split('-', $date);
$m = $month[int($m) - 1];
die "$MyName: date $date has illegal month\n" unless defined($m);
$d =~ s/^0//;
$date = "$m $d, $y";
} else {
$date = localtime;
$date =~ s/^\S+\s+//; # get rid of weekday
$date =~ s/\s+\d\d:\d\d:\d\d/,/; }
my $written;
for(@lines) {
if(/^Written/i) {
$written = $_;
last;
}
}
my $copyright;
for my $p (@pg) {
chomp($p);
if($p =~ /^Copyright/i) {
$copyright = $p;
next;
}
for(split("\n", $p)) {
if(/^Written/i) {
$written = $_;
last;
}
}
}
$output->print(".Dd $date\n");
(my $uppercmd = $cmd) =~ tr/a-z/A-Z/;
$output->print(".Dt $uppercmd $Section\n");
$output->print(".Os \"Mac OS X\"\n");
$output->print(".Sh NAME\n");
$output->print(".Nm $cmd\n");
$output->print(".Nd manual page for $version\n");
$output->print(".Sh SYNOPSIS\n");
@pg = split("\n\n", $cmdhelp);
my $usage = shift(@pg);
chomp($usage);
$usage =~ s/^Usage: \S+\s+//i;
$output->print(".Nm\n");
for(split(/(\[[^]]*\])/, $usage)) { if(s/^\[(.*)\]$/\1/) {
if(/^-/) {
s/ (\w)/ Ar \1/g;
s/--/@@/g; s/-/Fl /g;
s/@@/Fl \\-/g;
}
$output->print(".Op $_\n");
} elsif(length($_) > 0) {
$output->print("\\&$_\n");
}
}
$output->print(".Sh DESCRIPTION\n");
my $inPp = 0;
my $report;
my $out = $output;
for my $p (@pg) {
chomp($p);
if($p =~ /[^.]( | )/) { $out->print(".Pp\n") if $inPp;
$inPp = 1;
my @table;
my $len = 0;
my $next = 0;
my($k, $v, $l, $long);
for(split("\n", $p)) {
s/^\s+//;
if($next) {
$next = 0;
$v = $_;
} else {
($k, $v) = split(/(?: \s+| \s*)/, $_, 2);
$l = length($k);
if($l > $len) {
$long = $k;
$len = $l;
}
if(!defined($v) || $v eq '') {
$next++;
next;
}
}
push(@table, [$k, $v]);
}
$long =~ s/-/\\-/g;
$out->print(".Bl -tag -compact -width \"$long\"\n");
for(@table) {
my($k, $v) = @$_;
if($k =~ /^-/) {
$k =~ s/(\w)-(\w)/\1@@\2/g; $k =~ s/--/@@@/g; $k =~ s/-/Fl /g;
$k =~ s/@@@/Fl \\-/g;
$k =~ s/@@/-/g;
$k =~ s/,/ ,/g;
}
$out->print(".It $k\n");
$out->print("\\&$v\n");
}
$out->print(".El\n");
} elsif(!defined($report) && ($p =~ /^When reporting a bug/ || $p =~ /^Report bugs/)) {
$report = IO::String->new() or die "$MyName: IO::String->new failed\n";
$out = $report;
$inPp = 1;
$out->print("$p\n");
} else {
$out->print(".Pp\n") if $inPp;
$inPp = 1;
$out->print("$p\n");
}
}
if(defined($written)) {
$output->print(".Sh AUTHOR\n");
$output->print("$written\n");
}
if(defined($report) > 0) {
$output->print(".Sh REPORTING BUGS\n");
$output->print(${$report->string_ref});
}
if(defined($copyright)) {
$output->print(".Sh COPYRIGHT\n");
$output->print("$copyright\n");
}
$output->print(".Sh SEE ALSO\n");
$output->print(<<EOF);
The equivalent documentation for
.Nm
is maintained as a TexInfo manual,
and can be accessed with:
.Pp
.Dl info $cmd
.Pp
EOF
if(defined($ENV{HELP2MAN_SEE_ALSO})) {
(my $seealso = $ENV{HELP2MAN_SEE_ALSO}) =~ s/@@/\n/g;
chomp($seealso);
$output->print($seealso, "\n");
}