Blame man/help2man

Packit Service fdd496
#!/usr/bin/perl -w
Packit Service fdd496
Packit Service fdd496
# Generate a short man page from --help and --version output.
Packit Service fdd496
# Copyright (C) 1997-2005, 2009-2011, 2013, 2015-2017 Free Software Foundation,
Packit Service fdd496
# Inc.
Packit Service fdd496
Packit Service fdd496
# This program is free software; you can redistribute it and/or modify
Packit Service fdd496
# it under the terms of the GNU General Public License as published by
Packit Service fdd496
# the Free Software Foundation; either version 3, or (at your option)
Packit Service fdd496
# any later version.
Packit Service fdd496
Packit Service fdd496
# This program is distributed in the hope that it will be useful,
Packit Service fdd496
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
# GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
# You should have received a copy of the GNU General Public License
Packit Service fdd496
# along with this program; if not, write to the Free Software Foundation,
Packit Service fdd496
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Packit Service fdd496
Packit Service fdd496
# Written by Brendan O'Dea <bod@debian.org>
Packit Service fdd496
# Available from ftp://ftp.gnu.org/gnu/help2man/
Packit Service fdd496
Packit Service fdd496
use 5.008;
Packit Service fdd496
use strict;
Packit Service fdd496
use Getopt::Long;
Packit Service fdd496
use Text::Tabs qw(expand);
Packit Service fdd496
use POSIX qw(strftime setlocale LC_ALL);
Packit Service fdd496
Packit Service fdd496
my $this_program = 'help2man';
Packit Service fdd496
my $this_version = '1.40.4';
Packit Service fdd496
Packit Service fdd496
sub _ { $_[0] }
Packit Service fdd496
sub configure_locale
Packit Service fdd496
{
Packit Service fdd496
    my $locale = shift;
Packit Service fdd496
    die "$this_program: no locale support (Locale::gettext required)\n"
Packit Service fdd496
	unless $locale eq 'C';
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
sub dec { $_[0] }
Packit Service fdd496
sub enc { $_[0] }
Packit Service fdd496
sub enc_user { $_[0] }
Packit Service fdd496
sub kark { die +(sprintf shift, @_), "\n" }
Packit Service fdd496
sub N_ { $_[0] }
Packit Service fdd496
Packit Service fdd496
my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
Packit Service fdd496
GNU %s %s
Packit Service fdd496
Packit Service fdd496
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010,
Packit Service fdd496
2011 Free Software Foundation, Inc.
Packit Service fdd496
This is free software; see the source for copying conditions.  There is NO
Packit Service fdd496
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit Service fdd496
Packit Service fdd496
Written by Brendan O'Dea <bod@debian.org>
Packit Service fdd496
EOT
Packit Service fdd496
Packit Service fdd496
my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
Packit Service fdd496
'%s' generates a man page out of '--help' and '--version' output.
Packit Service fdd496
Packit Service fdd496
Usage: %s [OPTION]... EXECUTABLE
Packit Service fdd496
Packit Service fdd496
 -n, --name=STRING       description for the NAME paragraph
Packit Service fdd496
 -s, --section=SECTION   section number for manual page (1, 6, 8)
Packit Service fdd496
 -m, --manual=TEXT       name of manual (User Commands, ...)
Packit Service fdd496
 -S, --source=TEXT       source of program (FSF, Debian, ...)
Packit Service fdd496
 -L, --locale=STRING     select locale (default "C")
Packit Service fdd496
 -i, --include=FILE      include material from 'FILE'
Packit Service fdd496
 -I, --opt-include=FILE  include material from 'FILE' if it exists
Packit Service fdd496
 -o, --output=FILE       send output to 'FILE'
Packit Service fdd496
 -p, --info-page=TEXT    name of Texinfo manual
Packit Service fdd496
 -N, --no-info           suppress pointer to Texinfo manual
Packit Service fdd496
 -l, --libtool           exclude the 'lt-' from the program name
Packit Service fdd496
     --help              print this help, then exit
Packit Service fdd496
     --version           print version number, then exit
Packit Service fdd496
Packit Service fdd496
EXECUTABLE should accept '--help' and '--version' options and produce output on
Packit Service fdd496
stdout although alternatives may be specified using:
Packit Service fdd496
Packit Service fdd496
 -h, --help-option=STRING     help option string
Packit Service fdd496
 -v, --version-option=STRING  version option string
Packit Service fdd496
 --version-string=STRING      version string
Packit Service fdd496
 --no-discard-stderr          include stderr when parsing option output
Packit Service fdd496
Packit Service fdd496
Report bugs to <bug-help2man@gnu.org>.
Packit Service fdd496
EOT
Packit Service fdd496
Packit Service fdd496
my $section = 1;
Packit Service fdd496
my $manual = '';
Packit Service fdd496
my $source = '';
Packit Service fdd496
my $help_option = '--help';
Packit Service fdd496
my $version_option = '--version';
Packit Service fdd496
my $discard_stderr = 1;
Packit Service fdd496
my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
Packit Service fdd496
    $version_text);
Packit Service fdd496
Packit Service fdd496
my %opt_def = (
Packit Service fdd496
    'n|name=s'		 => \$opt_name,
Packit Service fdd496
    's|section=s'	 => \$section,
Packit Service fdd496
    'm|manual=s'	 => \$manual,
Packit Service fdd496
    'S|source=s'	 => \$source,
Packit Service fdd496
    'L|locale=s'	 => sub { configure_locale pop },
Packit Service fdd496
    'i|include=s'	 => sub { push @opt_include, [ pop, 1 ] },
Packit Service fdd496
    'I|opt-include=s'	 => sub { push @opt_include, [ pop, 0 ] },
Packit Service fdd496
    'o|output=s'	 => \$opt_output,
Packit Service fdd496
    'p|info-page=s'	 => \$opt_info,
Packit Service fdd496
    'N|no-info'		 => \$opt_no_info,
Packit Service fdd496
    'l|libtool'		 => \$opt_libtool,
Packit Service fdd496
    'help'		 => sub { print $help_info; exit },
Packit Service fdd496
    'version'		 => sub { print $version_info; exit },
Packit Service fdd496
    'h|help-option=s'	 => \$help_option,
Packit Service fdd496
    'v|version-option=s' => \$version_option,
Packit Service fdd496
    'version-string=s'	 => \$version_text,
Packit Service fdd496
    'discard-stderr!'	 => \$discard_stderr,
Packit Service fdd496
);
Packit Service fdd496
Packit Service fdd496
# Parse options.
Packit Service fdd496
Getopt::Long::config('bundling');
Packit Service fdd496
die $help_info unless GetOptions %opt_def and @ARGV == 1;
Packit Service fdd496
Packit Service fdd496
my %include = ();
Packit Service fdd496
my %append = ();
Packit Service fdd496
my @include = (); # retain order given in include file
Packit Service fdd496
Packit Service fdd496
# Process include file (if given).  Format is:
Packit Service fdd496
#
Packit Service fdd496
#   [section name]
Packit Service fdd496
#   verbatim text
Packit Service fdd496
#
Packit Service fdd496
# or
Packit Service fdd496
#
Packit Service fdd496
#   /pattern/
Packit Service fdd496
#   verbatim text
Packit Service fdd496
#
Packit Service fdd496
Packit Service fdd496
while (@opt_include)
Packit Service fdd496
{
Packit Service fdd496
    my ($inc, $required) = @{shift @opt_include};
Packit Service fdd496
Packit Service fdd496
    next unless -f $inc or $required;
Packit Service fdd496
    kark N_("%s: can't open '%s' (%s)"), $this_program, $inc, $!
Packit Service fdd496
	unless open INC, $inc;
Packit Service fdd496
Packit Service fdd496
    my $key;
Packit Service fdd496
    my $hash = \%include;
Packit Service fdd496
Packit Service fdd496
    while (<INC>)
Packit Service fdd496
    {
Packit Service fdd496
	# Convert input to internal Perl format, so that multibyte
Packit Service fdd496
	# sequences are treated as single characters.
Packit Service fdd496
	$_ = dec $_;
Packit Service fdd496
Packit Service fdd496
	# [section]
Packit Service fdd496
	if (/^\[([^]]+)\]\s*$/)
Packit Service fdd496
	{
Packit Service fdd496
	    $key = uc $1;
Packit Service fdd496
	    $key =~ s/^\s+//;
Packit Service fdd496
	    $key =~ s/\s+$//;
Packit Service fdd496
	    $hash = \%include;
Packit Service fdd496
	    push @include, $key unless $include{$key};
Packit Service fdd496
	    next;
Packit Service fdd496
	}
Packit Service fdd496
Packit Service fdd496
	# /pattern/
Packit Service fdd496
	if (m!^/(.*)/([ims]*)\s*$!)
Packit Service fdd496
	{
Packit Service fdd496
	    my $pat = $2 ? "(?$2)$1" : $1;
Packit Service fdd496
Packit Service fdd496
	    # Check pattern.
Packit Service fdd496
	    eval { $key = qr($pat) };
Packit Service fdd496
	    if ($@)
Packit Service fdd496
	    {
Packit Service fdd496
		$@ =~ s/ at .*? line \d.*//;
Packit Service fdd496
		die "$inc:$.:$@";
Packit Service fdd496
	    }
Packit Service fdd496
Packit Service fdd496
	    $hash = \%append;
Packit Service fdd496
	    next;
Packit Service fdd496
	}
Packit Service fdd496
Packit Service fdd496
	# Check for options before the first section--anything else is
Packit Service fdd496
	# silently ignored, allowing the first for comments and
Packit Service fdd496
	# revision info.
Packit Service fdd496
	unless ($key)
Packit Service fdd496
	{
Packit Service fdd496
	    # handle options
Packit Service fdd496
	    if (/^-/)
Packit Service fdd496
	    {
Packit Service fdd496
		local @ARGV = split;
Packit Service fdd496
		GetOptions %opt_def;
Packit Service fdd496
	    }
Packit Service fdd496
Packit Service fdd496
	    next;
Packit Service fdd496
	}
Packit Service fdd496
Packit Service fdd496
	$hash->{$key} ||= '';
Packit Service fdd496
	$hash->{$key} .= $_;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    close INC;
Packit Service fdd496
Packit Service fdd496
    kark N_("%s: no valid information found in '%s'"), $this_program, $inc
Packit Service fdd496
	unless $key;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Compress trailing blank lines.
Packit Service fdd496
for my $hash (\(%include, %append))
Packit Service fdd496
{
Packit Service fdd496
    for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
sub get_option_value;
Packit Service fdd496
Packit Service fdd496
# Grab help and version info from executable.
Packit Service fdd496
my $help_text   = get_option_value $ARGV[0], $help_option;
Packit Service fdd496
$version_text ||= get_option_value $ARGV[0], $version_option;
Packit Service fdd496
Packit Service fdd496
# Translators: the following message is a strftime(3) format string, which in
Packit Service fdd496
# the English version expands to the month as a word and the full year.  It
Packit Service fdd496
# is used on the footer of the generated manual pages.  If in doubt, you may
Packit Service fdd496
# just use %x as the value (which should be the full locale-specific date).
Packit Service fdd496
my $date = enc strftime _("%B %Y"), localtime;
Packit Service fdd496
(my $program = $ARGV[0]) =~ s!.*/!!;
Packit Service fdd496
my $package = $program;
Packit Service fdd496
my $version;
Packit Service fdd496
Packit Service fdd496
if ($opt_output)
Packit Service fdd496
{
Packit Service fdd496
    unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
Packit Service fdd496
	$this_program, $opt_output, $! if -e $opt_output;
Packit Service fdd496
Packit Service fdd496
    open STDOUT, ">$opt_output"
Packit Service fdd496
	or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# The first line of the --version information is assumed to be in one
Packit Service fdd496
# of the following formats:
Packit Service fdd496
#
Packit Service fdd496
#   <version>
Packit Service fdd496
#   <program> <version>
Packit Service fdd496
#   {GNU,Free} <program> <version>
Packit Service fdd496
#   <program> ({GNU,Free} <package>) <version>
Packit Service fdd496
#   <program> - {GNU,Free} <package> <version>
Packit Service fdd496
#
Packit Service fdd496
# and separated from any copyright/author details by a blank line.
Packit Service fdd496
Packit Service fdd496
($_, $version_text) = ((split /\n+/, $version_text, 2), '');
Packit Service fdd496
Packit Service fdd496
if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
Packit Service fdd496
    /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
Packit Service fdd496
{
Packit Service fdd496
    $program = $1;
Packit Service fdd496
    $package = $2;
Packit Service fdd496
    $version = $3;
Packit Service fdd496
}
Packit Service fdd496
elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
Packit Service fdd496
{
Packit Service fdd496
    $program = $2;
Packit Service fdd496
    $package = $1 ? "$1$2" : $2;
Packit Service fdd496
    $version = $3;
Packit Service fdd496
}
Packit Service fdd496
else
Packit Service fdd496
{
Packit Service fdd496
    $version = $_;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
$program =~ s!.*/!!;
Packit Service fdd496
Packit Service fdd496
# No info for 'info' itself.
Packit Service fdd496
$opt_no_info = 1 if $program eq 'info';
Packit Service fdd496
Packit Service fdd496
# Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
Packit Service fdd496
# upper case are manual page section headings.  The man(1) manual page in your
Packit Service fdd496
# language, if available should provide the conventional translations.
Packit Service fdd496
for ($include{_('NAME')})
Packit Service fdd496
{
Packit Service fdd496
    if ($opt_name) # --name overrides --include contents.
Packit Service fdd496
    {
Packit Service fdd496
	$_ = "$program \\- $opt_name\n";
Packit Service fdd496
    }
Packit Service fdd496
    elsif ($_) # Use first name given as $program
Packit Service fdd496
    {
Packit Service fdd496
	$program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
Packit Service fdd496
    }
Packit Service fdd496
    else # Set a default (useless) NAME paragraph.
Packit Service fdd496
    {
Packit Service fdd496
	$_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
Packit Service fdd496
	    $program, $version;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Man pages traditionally have the page title in caps.
Packit Service fdd496
my $PROGRAM = uc $program;
Packit Service fdd496
Packit Service fdd496
# Set default page head/footers
Packit Service fdd496
$source ||= "$program $version";
Packit Service fdd496
unless ($manual)
Packit Service fdd496
{
Packit Service fdd496
    for ($section)
Packit Service fdd496
    {
Packit Service fdd496
	if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') }
Packit Service fdd496
	elsif (/^6/)	  { $manual = enc _('Games') }
Packit Service fdd496
	else		  { $manual = enc _('User Commands') }
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Extract usage clause(s) [if any] for SYNOPSIS.
Packit Service fdd496
# Translators: "Usage" and "or" here are patterns (regular expressions) which
Packit Service fdd496
# are used to match the usage synopsis in program output.  An example from cp
Packit Service fdd496
# (GNU coreutils) which contains both strings:
Packit Service fdd496
#  Usage: cp [OPTION]... [-T] SOURCE DEST
Packit Service fdd496
#    or:  cp [OPTION]... SOURCE... DIRECTORY
Packit Service fdd496
#    or:  cp [OPTION]... -t DIRECTORY SOURCE...
Packit Service fdd496
my $PAT_USAGE = _('Usage');
Packit Service fdd496
my $PAT_USAGE_CONT = _('or');
Packit Service fdd496
if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
Packit Service fdd496
{
Packit Service fdd496
    my @syn = $3 . $4;
Packit Service fdd496
Packit Service fdd496
    if ($_ = $5)
Packit Service fdd496
    {
Packit Service fdd496
	s/^\n//;
Packit Service fdd496
	for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    my $synopsis = '';
Packit Service fdd496
    for (@syn)
Packit Service fdd496
    {
Packit Service fdd496
	$synopsis .= ".br\n" if $synopsis;
Packit Service fdd496
	s!^\S*/!!;
Packit Service fdd496
	s/^lt-// if $opt_libtool;
Packit Service fdd496
	s/^(\S+) *//;
Packit Service fdd496
	$synopsis .= ".B $1\n";
Packit Service fdd496
	s/\s+$//;
Packit Service fdd496
	s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
Packit Service fdd496
	s/^/\\fI/ unless s/^\\fR//;
Packit Service fdd496
	$_ .= '\fR';
Packit Service fdd496
	s/(\\fI)( *)/$2$1/g;
Packit Service fdd496
	s/\\fI\\fR//g;
Packit Service fdd496
	s/^\\fR//;
Packit Service fdd496
	s/\\fI$//;
Packit Service fdd496
	s/^\./\\&.;;
Packit Service fdd496
Packit Service fdd496
	$synopsis .= "$_\n";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    $include{_('SYNOPSIS')} ||= $synopsis;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Process text, initial section is DESCRIPTION.
Packit Service fdd496
my $sect = _('DESCRIPTION');
Packit Service fdd496
$_ = "$help_text\n\n$version_text";
Packit Service fdd496
Packit Service fdd496
# Normalise paragraph breaks.
Packit Service fdd496
s/^\n+//;
Packit Service fdd496
s/\n*$/\n/;
Packit Service fdd496
s/\n\n+/\n\n/g;
Packit Service fdd496
Packit Service fdd496
# Join hyphenated lines.
Packit Service fdd496
s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
Packit Service fdd496
Packit Service fdd496
# Temporarily exchange leading dots, apostrophes and backslashes for
Packit Service fdd496
# tokens.
Packit Service fdd496
s/^\./\x80/mg;
Packit Service fdd496
s/^'/\x81/mg;
Packit Service fdd496
s/\\/\x82/g;
Packit Service fdd496
Packit Service fdd496
# Translators: patterns are used to match common program output. In the source
Packit Service fdd496
# these strings are all of the form of "my $PAT_something = _('...');" and are
Packit Service fdd496
# regular expressions.  If there is more than one commonly used string, you
Packit Service fdd496
# may separate alternatives with "|".  Spaces in these expressions are written
Packit Service fdd496
# as " +" to indicate that more than one space may be matched.  The string
Packit Service fdd496
# "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
Packit Service fdd496
# optional word, so that either "Report bugs" or "Report _program_ bugs" will
Packit Service fdd496
# be matched.
Packit Service fdd496
my $PAT_BUGS		= _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to');
Packit Service fdd496
my $PAT_AUTHOR		= _('Written +by');
Packit Service fdd496
my $PAT_OPTIONS		= _('Options');
Packit Service fdd496
my $PAT_ENVIRONMENT	= _('Environment');
Packit Service fdd496
my $PAT_FILES		= _('Files');
Packit Service fdd496
my $PAT_EXAMPLES	= _('Examples');
Packit Service fdd496
my $PAT_FREE_SOFTWARE	= _('This +is +free +software');
Packit Service fdd496
Packit Service fdd496
# Start a new paragraph (if required) for these.
Packit Service fdd496
s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og;
Packit Service fdd496
Packit Service fdd496
# Convert iso-8859-1 copyright symbol or (c) to nroff
Packit Service fdd496
# character.
Packit Service fdd496
s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
Packit Service fdd496
Packit Service fdd496
sub convert_option;
Packit Service fdd496
Packit Service fdd496
while (length)
Packit Service fdd496
{
Packit Service fdd496
    # Convert some standard paragraph names.
Packit Service fdd496
    if (s/^($PAT_OPTIONS): *\n//o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('OPTIONS');
Packit Service fdd496
	next;
Packit Service fdd496
    }
Packit Service fdd496
    if (s/^($PAT_ENVIRONMENT): *\n//o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('ENVIRONMENT');
Packit Service fdd496
	next;
Packit Service fdd496
    }
Packit Service fdd496
    if (s/^($PAT_FILES): *\n//o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('FILES');
Packit Service fdd496
	next;
Packit Service fdd496
    }
Packit Service fdd496
    elsif (s/^($PAT_EXAMPLES): *\n//o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('EXAMPLES');
Packit Service fdd496
	next;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Copyright section
Packit Service fdd496
    if (/^Copyright /)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('COPYRIGHT');
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Bug reporting section.
Packit Service fdd496
    elsif (/^($PAT_BUGS) /o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('REPORTING BUGS');
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Author section.
Packit Service fdd496
    elsif (/^($PAT_AUTHOR)/o)
Packit Service fdd496
    {
Packit Service fdd496
	$sect = _('AUTHOR');
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Examples, indicated by an indented leading $, % or > are
Packit Service fdd496
    # rendered in a constant width font.
Packit Service fdd496
    if (/^( +)([\$\%>] )\S/)
Packit Service fdd496
    {
Packit Service fdd496
	my $indent = $1;
Packit Service fdd496
	my $prefix = $2;
Packit Service fdd496
	my $break = '.IP';
Packit Service fdd496
	$include{$sect} ||= '';
Packit Service fdd496
	while (s/^$indent\Q$prefix\E(\S.*)\n*//)
Packit Service fdd496
	{
Packit Service fdd496
	    $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
Packit Service fdd496
	    $break = '.br';
Packit Service fdd496
	}
Packit Service fdd496
Packit Service fdd496
	next;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    my $matched = '';
Packit Service fdd496
    $include{$sect} ||= '';
Packit Service fdd496
Packit Service fdd496
    # Sub-sections have a trailing colon and the second line indented.
Packit Service fdd496
    if (s/^(\S.*:) *\n / /)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$include{$sect} .= qq(.SS "$1"\n);
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    my $indent = 0;
Packit Service fdd496
    my $content = '';
Packit Service fdd496
Packit Service fdd496
    # Option with description.
Packit Service fdd496
    if (s/^( {1,10}([+-]\S.*?))(?:(  +(?!-))|\n( {20,}))(\S.*)\n//)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$indent = length ($4 || "$1$3");
Packit Service fdd496
	$content = ".TP\n\x84$2\n\x84$5\n";
Packit Service fdd496
	unless ($4)
Packit Service fdd496
	{
Packit Service fdd496
	    # Indent may be different on second line.
Packit Service fdd496
	    $indent = length $& if /^ {20,}/;
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Option without description.
Packit Service fdd496
    elsif (s/^ {1,10}([+-]\S.*)\n//)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$content = ".HP\n\x84$1\n";
Packit Service fdd496
	$indent = 80; # not continued
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Indented paragraph with tag.
Packit Service fdd496
    elsif (s/^( +(\S.*?)  +)(\S.*)\n//)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$indent = length $1;
Packit Service fdd496
	$content = ".TP\n\x84$2\n\x84$3\n";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Indented paragraph.
Packit Service fdd496
    elsif (s/^( +)(\S.*)\n//)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$indent = length $1;
Packit Service fdd496
	$content = ".IP\n\x84$2\n";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Left justified paragraph.
Packit Service fdd496
    else
Packit Service fdd496
    {
Packit Service fdd496
	s/(.*)\n//;
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$content = ".PP\n" if $include{$sect};
Packit Service fdd496
	$content .= "$1\n";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Append continuations.
Packit Service fdd496
    while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
Packit Service fdd496
    {
Packit Service fdd496
	$matched .= $& if %append;
Packit Service fdd496
	$content .= "\x84$1\n";
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Move to next paragraph.
Packit Service fdd496
    s/^\n+//;
Packit Service fdd496
Packit Service fdd496
    for ($content)
Packit Service fdd496
    {
Packit Service fdd496
	# Leading dot and apostrophe protection.
Packit Service fdd496
	s/\x84\./\x80/g;
Packit Service fdd496
	s/\x84'/\x81/g;
Packit Service fdd496
	s/\x84//g;
Packit Service fdd496
Packit Service fdd496
	# Convert options.
Packit Service fdd496
	s/(^| |\()(-[][\w=-]+)/$1 . convert_option $2/mge;
Packit Service fdd496
Packit Service fdd496
	# Escape remaining hyphens
Packit Service fdd496
	s/-/\x83/g;
Packit Service fdd496
Packit Service fdd496
	if ($sect eq 'COPYRIGHT')
Packit Service fdd496
	{
Packit Service fdd496
	    # Insert line breaks before additional copyright messages
Packit Service fdd496
	    # and the disclaimer.
Packit Service fdd496
	    s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
Packit Service fdd496
	}
Packit Service fdd496
	elsif ($sect eq 'REPORTING BUGS')
Packit Service fdd496
	{
Packit Service fdd496
	    # Handle multi-line bug reporting sections of the form:
Packit Service fdd496
	    #
Packit Service fdd496
	    #   Report <program> bugs to <addr>
Packit Service fdd496
	    #   GNU <package> home page: <url>
Packit Service fdd496
	    #   ...
Packit Service fdd496
	    s/\n([[:upper:]])/\n.br\n$1/g;
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    # Check if matched paragraph contains /pat/.
Packit Service fdd496
    if (%append)
Packit Service fdd496
    {
Packit Service fdd496
	for my $pat (keys %append)
Packit Service fdd496
	{
Packit Service fdd496
	    if ($matched =~ $pat)
Packit Service fdd496
	    {
Packit Service fdd496
		$content .= ".PP\n" unless $append{$pat} =~ /^\./;
Packit Service fdd496
		$content .= $append{$pat};
Packit Service fdd496
	    }
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    $include{$sect} .= $content;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Refer to the real documentation.
Packit Service fdd496
unless ($opt_no_info)
Packit Service fdd496
{
Packit Service fdd496
    my $info_page = $opt_info || $program;
Packit Service fdd496
Packit Service fdd496
    $sect = _('SEE ALSO');
Packit Service fdd496
    $include{$sect} ||= '';
Packit Service fdd496
    $include{$sect} .= ".PP\n" if $include{$sect};
Packit Service fdd496
    $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
Packit Service fdd496
The full documentation for
Packit Service fdd496
.B %s
Packit Service fdd496
is maintained as a Texinfo manual.  If the
Packit Service fdd496
.B info
Packit Service fdd496
and
Packit Service fdd496
.B %s
Packit Service fdd496
programs are properly installed at your site, the command
Packit Service fdd496
.IP
Packit Service fdd496
.B info %s
Packit Service fdd496
.PP
Packit Service fdd496
should give you access to the complete manual.
Packit Service fdd496
EOT
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Output header.
Packit Service fdd496
print <
Packit Service fdd496
.\\" DO NOT MODIFY THIS FILE!  It was generated by $this_program $this_version.
Packit Service fdd496
.TH $PROGRAM "$section" "$date" "$source" "$manual"
Packit Service fdd496
EOT
Packit Service fdd496
Packit Service fdd496
# Section ordering.
Packit Service fdd496
my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
Packit Service fdd496
    _('ENVIRONMENT'), _('FILES'), _('EXAMPLES'));
Packit Service fdd496
Packit Service fdd496
my @post = (_('AUTHOR'), _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
Packit Service fdd496
my $filter = join '|', @pre, @post;
Packit Service fdd496
Packit Service fdd496
# Output content.
Packit Service fdd496
for my $sect (@pre, (grep ! /^($filter)$/o, @include), @post)
Packit Service fdd496
{
Packit Service fdd496
    if ($include{$sect})
Packit Service fdd496
    {
Packit Service fdd496
	my $quote = $sect =~ /\W/ ? '"' : '';
Packit Service fdd496
	print enc ".SH $quote$sect$quote\n";
Packit Service fdd496
Packit Service fdd496
	for ($include{$sect})
Packit Service fdd496
	{
Packit Service fdd496
	    # Replace leading dot, apostrophe, backslash and hyphen
Packit Service fdd496
	    # tokens.
Packit Service fdd496
	    s/\x80/\\&./g;
Packit Service fdd496
	    s/\x81/\\&'/g;
Packit Service fdd496
	    s/\x82/\\e/g;
Packit Service fdd496
	    s/\x83/\\-/g;
Packit Service fdd496
Packit Service fdd496
	    # Convert some latin1 chars to troff equivalents
Packit Service fdd496
	    s/\xa0/\\ /g; # non-breaking space
Packit Service fdd496
Packit Service fdd496
	    print enc $_;
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
Packit Service fdd496
    $opt_output || 'stdout', $!;
Packit Service fdd496
Packit Service fdd496
exit;
Packit Service fdd496
Packit Service fdd496
# Call program with given option and return results.
Packit Service fdd496
sub get_option_value
Packit Service fdd496
{
Packit Service fdd496
    my ($prog, $opt) = @_;
Packit Service fdd496
    my $stderr = $discard_stderr ? '/dev/null' : '&1;;
Packit Service fdd496
    my $value = join '',
Packit Service fdd496
	map { s/ +$//; expand $_ }
Packit Service fdd496
	map { dec $_ }
Packit Service fdd496
	`$prog $opt 2>$stderr`;
Packit Service fdd496
Packit Service fdd496
    unless ($value)
Packit Service fdd496
    {
Packit Service fdd496
	my $err = N_("%s: can't get '%s' info from %s%s");
Packit Service fdd496
	my $extra = $discard_stderr
Packit Service fdd496
	    ? "\n" . N_("Try '--no-discard-stderr' if option outputs to stderr")
Packit Service fdd496
	    : '';
Packit Service fdd496
Packit Service fdd496
	kark $err, $this_program, $opt, $prog, $extra;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    return $value;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# Convert option dashes to \- to stop nroff from hyphenating 'em, and
Packit Service fdd496
# embolden.  Option arguments get italicised.
Packit Service fdd496
sub convert_option
Packit Service fdd496
{
Packit Service fdd496
    local $_ = '\fB' . shift;
Packit Service fdd496
Packit Service fdd496
    s/-/\x83/g;
Packit Service fdd496
    unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
Packit Service fdd496
    {
Packit Service fdd496
	s/=(.)/\\fR=\\fI$1/;
Packit Service fdd496
	s/ (.)/ \\fI$1/;
Packit Service fdd496
	$_ .= '\fR';
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    $_;
Packit Service fdd496
}