#!/usr/bin/env perl
# Make qperf man page.
#
use strict;
use warnings;
use diagnostics;
use POSIX;


my $help_txt  = "help.txt";


# Print out an error message and exit.
#
sub panic {
    print STDERR @_, "\n";
    exit 1;
}


# Print arguments to stdout.
#
sub printx {
    print STDOUT "@_";
}


# Print arguments along with a newline to stdout.
#
sub printn {
    print STDOUT "@_\n";
}


# Print a sub-heading as required in upper-case.
#
sub printh ($) {
    my $name = shift;
    printn ".SH ", uc $name;
}


# Undent some text by four columns.
#
sub undent {
    my $str = shift;
    $str =~ s/^    //gm;
    return $str;
}


# Generate the list of tests from the help.txt file.
#
sub do_tests ($$) {
    my $dict = shift;
    my $name = shift;
    my $text = $dict->{"Tests +RDMA"};
    printh $name;
    $text =~ s/^\s*//;
    my @lines = split(/\n/, $text);
    for (@lines) {
        next unless /^ {8}(\w+)\s+(.*)/;
        printn '.TP';
        printn "\\fB$1\\fP";
        printn $2;
    }
}


# Generate the list of options from the help.txt file.
#
sub do_options ($$) {
    my $dict = shift;
    my $name = shift;
    my $text = $dict->{$name};
    printh $name;
    $text =~ s/^\s*//;
    my @options = split(/^\s{4,6}(?=-)/m, $text);
    for my $option (@options) {
        $option =~ s/(.*)\n\s*//;
        my $head = $1;
        my $line = "";
        ($head =~ s/(.*)\s+\((-\w+)\)/$1/) and
            $line = "\\fB$2\\fP, ";
        $head =~ /(\S+)\s*(.*)/;
        $line .= "\\fB$1\\fP";
        $line .= " \\fI$2\\fP" if $2;
        printn '.TP';
        printn $line;
        $option =~ s/^\s+//mg;
        $option =~ s/\s+$//;
        printn $option;
    }
}


# Generate the list of examples from the help.txt file.
#
sub do_examples ($$) {
    my $dict = shift;
    my $name = shift;
    my $text = $dict->{$name};
    printh $name;
    my @lines = split(/^ {8}\* /m, $text);
    printx undent(shift @lines);
    for (@lines) {
        s/(.*)\n//;
        printn '.TP';
        printn $1;
        s/^\s+//m;
        print $_;
    }
}


# Generate the synopsis from the help.txt file.
#
sub do_synopsis ($$) {
    my $dict = shift;
    my $name = shift;
    my $text = $dict->{$name};
    printh $name;
    $text =~ s/([A-Z]+)/\\fI$1\\fP/g;
    $text =~ s/(qperf)/\\fB$1\\fP/g;
    $text =~ s/\n/\n.br\n/g;
    printx undent $text;
}


# Put out a sub-section that is gotten from a subsection within the Main
# section of the help.txt file.
#
sub do_general ($$) {
    my $dict = shift;
    my $name = shift;
    printh $name;
    printx undent $dict->{$name};
}


# Return the month and year that the help.txt file was last modified.
#
sub help_date() {
    my @info = stat $help_txt or
        panic("Cannot find $help_txt");
    return POSIX::strftime "%B %Y", localtime($info[9]);
}


# Make a dictionary from text with the keys generated from text that is flush
# agains the left column and its associated data being the text that is
# subsequently indented.
#
sub make_dict ($) {
    my %dict;
    my $data = shift;
    my @entrys = split(/^(?=\S)/m, $data);
    (s/^(.*)\n//) and
        $dict{$1} = $_
            for (@entrys);
    return \%dict;
}


# Return the contents of the help.txt file.
#
sub read_file ($) {
    my $name = shift;
    my $file;
    local $/;
    open($file, "<", $name) or
        panic("Cannot find $name");
    my $data = <$file>;
    close $file;
    return $data;
}


sub main() {
    my $data = read_file $help_txt;
    my $help = make_dict $data;
    my $main = make_dict undent $help->{Main};

    printn '.\" Generated by mkman';
    printn '.TH QPERF 1 "' . help_date . '" "qperf" "User Commands"';
    printn '.SH NAME';
    printn 'qperf \- Measure RDMA and IP performance';

    do_synopsis ($main, 'Synopsis');
    do_general  ($main, 'Description');
    do_examples ($help, 'Examples');
    do_options  ($help, 'Options');
    do_tests    ($help, 'Tests');
    do_general  ($help, 'Author');
    do_general  ($help, 'Bugs');
}

main();
