1a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#!/usr/bin/env perl
2a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
3a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Generate a short man page from --help and --version output.
4a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software
5a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Foundation, Inc.
6a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
7a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# This program is free software; you can redistribute it and/or modify
8a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# it under the terms of the GNU General Public License as published by
9a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# the Free Software Foundation; either version 2, or (at your option)
10a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# any later version.
11a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
12a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# This program is distributed in the hope that it will be useful,
13a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# but WITHOUT ANY WARRANTY; without even the implied warranty of
14a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# GNU General Public License for more details.
16a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
17a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# You should have received a copy of the GNU General Public License
18a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# along with this program; if not, write to the Free Software Foundation,
19a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
21a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Written by Brendan O'Dea <bod@debian.org>
22a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Available from ftp://ftp.gnu.org/gnu/help2man/
23a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
24a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneruse 5.005;
25a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneruse strict;
26a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneruse Getopt::Long;
27a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneruse Text::Tabs qw(expand);
28a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneruse POSIX qw(strftime setlocale LC_TIME);
29a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
30a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $this_program = 'help2man';
31a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $this_version = '1.28';
32a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $version_info = <<EOT;
33a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerGNU $this_program $this_version
34a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
35a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerCopyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
36a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerThis is free software; see the source for copying conditions.  There is NO
37a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
38a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
39a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerWritten by Brendan O'Dea <bod\@debian.org>
40a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerEOT
41a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
42a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $help_info = <<EOT;
43a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner`$this_program' generates a man page out of `--help' and `--version' output.
44a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
45a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerUsage: $this_program [OPTION]... EXECUTABLE
46a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
47a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -n, --name=STRING       description for the NAME paragraph
48a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -s, --section=SECTION   section number for manual page (1, 6, 8)
49a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -m, --manual=TEXT       name of manual (User Commands, ...)
50a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -S, --source=TEXT       source of program (FSF, Debian, ...)
51a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -i, --include=FILE      include material from `FILE'
52a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -I, --opt-include=FILE  include material from `FILE' if it exists
53a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -o, --output=FILE       send output to `FILE'
54a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -p, --info-page=TEXT    name of Texinfo manual
55a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -N, --no-info           suppress pointer to Texinfo manual
56a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     --help              print this help, then exit
57a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner     --version           print version number, then exit
58a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
59a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerEXECUTABLE should accept `--help' and `--version' options although
60a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneralternatives may be specified using:
61a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
62a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -h, --help-option=STRING     help option string
63a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner -v, --version-option=STRING  version option string
64a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
65a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerReport bugs to <bug-help2man\@gnu.org>.
66a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerEOT
67a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
68a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $section = 1;
69a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $manual = '';
70a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $source = '';
71a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $help_option = '--help';
72a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $version_option = '--version';
73a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info);
74a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
75a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy %opt_def = (
76a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'n|name=s'		 => \$opt_name,
77a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    's|section=s'	 => \$section,
78a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'm|manual=s'	 => \$manual,
79a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'S|source=s'	 => \$source,
80a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'i|include=s'	 => sub { push @opt_include, [ pop, 1 ] },
81a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'I|opt-include=s'	 => sub { push @opt_include, [ pop, 0 ] },
82a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'o|output=s'	 => \$opt_output,
83a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'p|info-page=s'	 => \$opt_info,
84a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'N|no-info'		 => \$opt_no_info,
85a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'h|help-option=s'	 => \$help_option,
86a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    'v|version-option=s' => \$version_option,
87a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner);
88a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
89a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Parse options.
90a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerGetopt::Long::config('bundling');
91a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerGetOptions (%opt_def,
92a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    help    => sub { print $help_info; exit },
93a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    version => sub { print $version_info; exit },
94a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner) or die $help_info;
95a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
96a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerdie $help_info unless @ARGV == 1;
97a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
98a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy %include = ();
99a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy %append = ();
100a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy @include = (); # retain order given in include file
101a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
102a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Process include file (if given).  Format is:
103a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
104a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   [section name]
105a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   verbatim text
106a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
107a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# or
108a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
109a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   /pattern/
110a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   verbatim text
111a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
112a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
113a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerwhile (@opt_include)
114a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
115a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my ($inc, $required) = @{shift @opt_include};
116a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
117a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    next unless -f $inc or $required;
118a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    die "$this_program: can't open `$inc' ($!)\n"
119a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	unless open INC, $inc;
120a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
121a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $key;
122a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $hash = \%include;
123a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
124a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    while (<INC>)
125a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
126a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# [section]
127a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	if (/^\[([^]]+)\]/)
128a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
129a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $key = uc $1;
130a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $key =~ s/^\s+//;
131a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $key =~ s/\s+$//;
132a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $hash = \%include;
133a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    push @include, $key unless $include{$key};
134a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    next;
135a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
136a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
137a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# /pattern/
138a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	if (m!^/(.*)/([ims]*)!)
139a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
140a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    my $pat = $2 ? "(?$2)$1" : $1;
141a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
142a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Check pattern.
143a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    eval { $key = qr($pat) };
144a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    if ($@)
145a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    {
146a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		$@ =~ s/ at .*? line \d.*//;
147a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		die "$inc:$.:$@";
148a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    }
149a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
150a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $hash = \%append;
151a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    next;
152a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
153a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
154a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# Check for options before the first section--anything else is
155a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# silently ignored, allowing the first for comments and
156a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# revision info.
157a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	unless ($key)
158a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
159a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # handle options
160a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    if (/^-/)
161a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    {
162a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		local @ARGV = split;
163a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		GetOptions %opt_def;
164a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    }
165a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
166a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    next;
167a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
168a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
169a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$hash->{$key} ||= '';
170a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$hash->{$key} .= $_;
171a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
172a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
173a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    close INC;
174a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
175a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    die "$this_program: no valid information found in `$inc'\n"
176a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	unless $key;
177a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
178a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
179a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Compress trailing blank lines.
180a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerfor my $hash (\(%include, %append))
181a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
182a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
183a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
184a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
185a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Turn off localisation of executable's ouput.
186a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
187a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
188a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Turn off localisation of date (for strftime).
189a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnersetlocale LC_TIME, 'C';
190a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
191a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Grab help and version info from executable.
192a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy ($help_text, $version_text) = map {
193a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    join '', map { s/ +$//; expand $_ } `$ARGV[0] $_ 2>/dev/null`
194a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	or die "$this_program: can't get `$_' info from $ARGV[0]\n"
195a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner} $help_option, $version_option;
196a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
197a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $date = strftime "%B %Y", localtime;
198a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner(my $program = $ARGV[0]) =~ s!.*/!!;
199a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $package = $program;
200a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $version;
201a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
202a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerif ($opt_output)
203a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
204a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    unlink $opt_output
205a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	or die "$this_program: can't unlink $opt_output ($!)\n"
206a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	if -e $opt_output;
207a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
208a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    open STDOUT, ">$opt_output"
209a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	or die "$this_program: can't create $opt_output ($!)\n";
210a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
211a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
212a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# The first line of the --version information is assumed to be in one
213a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# of the following formats:
214a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
215a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   <version>
216a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   <program> <version>
217a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   {GNU,Free} <program> <version>
218a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   <program> ({GNU,Free} <package>) <version>
219a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#   <program> - {GNU,Free} <package> <version>
220a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner#
221a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# and seperated from any copyright/author details by a blank line.
222a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
223a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner($_, $version_text) = split /\n+/, $version_text, 2;
224a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
225a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerif (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
226a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
227a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
228a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $program = $1;
229a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $package = $2;
230a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $version = $3;
231a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
232a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerelsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
233a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
234a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $program = $2;
235a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $package = $1 ? "$1$2" : $2;
236a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $version = $3;
237a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
238a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerelse
239a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
240a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $version = $_;
241a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
242a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
243a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$program =~ s!.*/!!;
244a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
245a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# No info for `info' itself.
246a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$opt_no_info = 1 if $program eq 'info';
247a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
248a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# --name overrides --include contents.
249a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$include{NAME} = "$program \\- $opt_name\n" if $opt_name;
250a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
251a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Default (useless) NAME paragraph.
252a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$include{NAME} ||= "$program \\- manual page for $program $version\n";
253a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
254a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Man pages traditionally have the page title in caps.
255a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $PROGRAM = uc $program;
256a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
257a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Set default page head/footers
258a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$source ||= "$program $version";
259a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerunless ($manual)
260a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
261a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    for ($section)
262a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
263a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	if (/^(1[Mm]|8)/) { $manual = 'System Administration Utilities' }
264a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	elsif (/^6/)	  { $manual = 'Games' }
265a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	else		  { $manual = 'User Commands' }
266a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
267a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
268a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
269a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Extract usage clause(s) [if any] for SYNOPSIS.
270a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerif ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m)
271a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
272a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my @syn = $2 . $3;
273a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
274a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if ($_ = $4)
275a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
276a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/^\n//;
277a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ }
278a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
279a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
280a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $synopsis = '';
281a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    for (@syn)
282a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
283a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$synopsis .= ".br\n" if $synopsis;
284a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s!^\S*/!!;
285a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/^(\S+) *//;
286a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$synopsis .= ".B $1\n";
287a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\s+$//;
288a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
289a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/^/\\fI/ unless s/^\\fR//;
290a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$_ .= '\fR';
291a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/(\\fI)( *)/$2$1/g;
292a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\\fI\\fR//g;
293a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/^\\fR//;
294a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\\fI$//;
295a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/^\./\\&./;
296a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
297a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$synopsis .= "$_\n";
298a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
299a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
300a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{SYNOPSIS} ||= $synopsis;
301a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
302a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
303a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Process text, initial section is DESCRIPTION.
304a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $sect = 'DESCRIPTION';
305a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner$_ = "$help_text\n\n$version_text";
306a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
307a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Normalise paragraph breaks.
308a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/^\n+//;
309a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/\n*$/\n/;
310a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/\n\n+/\n\n/g;
311a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
312a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Temporarily exchange leading dots, apostrophes and backslashes for
313a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# tokens.
314a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/^\./\x80/mg;
315a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/^'/\x81/mg;
316a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/\\/\x82/g;
317a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
318a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Start a new paragraph (if required) for these.
319a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turners/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g;
320a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
321a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnersub convert_option;
322a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
323a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerwhile (length)
324a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
325a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Convert some standard paragraph names.
326a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (s/^(Options|Examples): *\n//)
327a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
328a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$sect = uc $1;
329a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	next;
330a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
331a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
332a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Copyright section
333a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (/^Copyright +[(\xa9]/)
334a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
335a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$sect = 'COPYRIGHT';
336a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$include{$sect} ||= '';
337a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$include{$sect} .= ".PP\n" if $include{$sect};
338a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
339a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	my $copy;
340a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	($copy, $_) = split /\n\n/, $_, 2;
341a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
342a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	for ($copy)
343a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
344a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Add back newline
345a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/\n*$/\n/;
346a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
347a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Convert iso9959-1 copyright symbol or (c) to nroff
348a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # character.
349a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
350a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
351a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Insert line breaks before additional copyright messages
352a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # and the disclaimer.
353a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g;
354a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
355a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Join hyphenated lines.
356a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/([A-Za-z])-\n */$1/g;
357a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
358a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
359a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$include{$sect} .= $copy;
360a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$_ ||= '';
361a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	next;
362a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
363a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
364a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Catch bug report text.
365a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (/^(Report +bugs|Email +bug +reports +to) /)
366a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
367a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$sect = 'REPORTING BUGS';
368a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
369a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
370a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Author section.
371a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    elsif (/^Written +by/)
372a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
373a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$sect = 'AUTHOR';
374a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
375a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
376a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Examples, indicated by an indented leading $, % or > are
377a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # rendered in a constant width font.
378a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (/^( +)([\$\%>] )\S/)
379a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
380a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	my $indent = $1;
381a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	my $prefix = $2;
382a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	my $break = '.IP';
383a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$include{$sect} ||= '';
384a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	while (s/^$indent\Q$prefix\E(\S.*)\n*//)
385a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
386a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
387a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $break = '.br';
388a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
389a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
390a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	next;
391a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
392a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
393a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $matched = '';
394a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{$sect} ||= '';
395a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
396a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Sub-sections have a trailing colon and the second line indented.
397a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (s/^(\S.*:) *\n / /)
398a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
399a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
400a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$include{$sect} .= qq(.SS "$1"\n);
401a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
402a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
403a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $indent = 0;
404a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $content = '';
405a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
406a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Option with description.
407a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (s/^( {1,10}([+-]\S.*?))(?:(  +(?!-))|\n( {20,}))(\S.*)\n//)
408a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
409a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
410a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$indent = length ($4 || "$1$3");
411a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content = ".TP\n\x83$2\n\x83$5\n";
412a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	unless ($4)
413a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
414a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Indent may be different on second line.
415a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    $indent = length $& if /^ {20,}/;
416a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
417a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
418a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
419a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Option without description.
420a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    elsif (s/^ {1,10}([+-]\S.*)\n//)
421a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
422a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
423a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content = ".HP\n\x83$1\n";
424a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$indent = 80; # not continued
425a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
426a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
427a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Indented paragraph with tag.
428a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    elsif (s/^( +(\S.*?)  +)(\S.*)\n//)
429a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
430a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
431a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$indent = length $1;
432a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content = ".TP\n\x83$2\n\x83$3\n";
433a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
434a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
435a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Indented paragraph.
436a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    elsif (s/^( +)(\S.*)\n//)
437a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
438a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
439a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$indent = length $1;
440a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content = ".IP\n\x83$2\n";
441a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
442a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
443a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Left justified paragraph.
444a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    else
445a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
446a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/(.*)\n//;
447a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
448a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content = ".PP\n" if $include{$sect};
449a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content .= "$1\n";
450a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
451a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
452a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Append continuations.
453a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    while (s/^ {$indent}(\S.*)\n//)
454a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
455a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$matched .= $& if %append;
456a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$content .= "\x83$1\n"
457a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
458a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
459a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Move to next paragraph.
460a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    s/^\n+//;
461a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
462a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    for ($content)
463a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
464a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# Leading dot and apostrophe protection.
465a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\x83\./\x80/g;
466a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\x83'/\x81/g;
467a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/\x83//g;
468a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
469a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	# Convert options.
470a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge;
471a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
472a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
473a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    # Check if matched paragraph contains /pat/.
474a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if (%append)
475a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
476a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	for my $pat (keys %append)
477a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
478a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    if ($matched =~ $pat)
479a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    {
480a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		$content .= ".PP\n" unless $append{$pat} =~ /^\./;
481a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner		$content .= $append{$pat};
482a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    }
483a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
484a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
485a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
486a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{$sect} .= $content;
487a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
488a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
489a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Refer to the real documentation.
490a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerunless ($opt_no_info)
491a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
492a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    my $info_page = $opt_info || $program;
493a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
494a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $sect = 'SEE ALSO';
495a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{$sect} ||= '';
496a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{$sect} .= ".PP\n" if $include{$sect};
497a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $include{$sect} .= <<EOT;
498a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerThe full documentation for
499a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.B $program
500a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turneris maintained as a Texinfo manual.  If the
501a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.B info
502a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerand
503a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.B $program
504a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerprograms are properly installed at your site, the command
505a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.IP
506a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.B info $info_page
507a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.PP
508a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnershould give you access to the complete manual.
509a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerEOT
510a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
511a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
512a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Output header.
513a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerprint <<EOT;
514a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.\\" DO NOT MODIFY THIS FILE!  It was generated by $this_program $this_version.
515a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner.TH $PROGRAM "$section" "$date" "$source" "$manual"
516a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' TurnerEOT
517a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
518a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Section ordering.
519a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy @pre = qw(NAME SYNOPSIS DESCRIPTION OPTIONS EXAMPLES);
520a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy @post = ('AUTHOR', 'REPORTING BUGS', 'COPYRIGHT', 'SEE ALSO');
521a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnermy $filter = join '|', @pre, @post;
522a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
523a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Output content.
524a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerfor (@pre, (grep ! /^($filter)$/o, @include), @post)
525a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
526a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    if ($include{$_})
527a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
528a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	my $quote = /\W/ ? '"' : '';
529a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	print ".SH $quote$_$quote\n";
530a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	
531a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	for ($include{$_})
532a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	{
533a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    # Replace leading dot, apostrophe and backslash tokens.
534a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/\x80/\\&./g;
535a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/\x81/\\&'/g;
536a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    s/\x82/\\e/g;
537a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	    print;
538a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	}
539a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
540a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
541a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
542a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnerexit;
543a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
544a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# Convert option dashes to \- to stop nroff from hyphenating 'em, and
545a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner# embolden.  Option arguments get italicised.
546a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turnersub convert_option
547a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner{
548a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    local $_ = '\fB' . shift;
549a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
550a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    s/-/\\-/g;
551a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
552a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    {
553a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/=(.)/\\fR=\\fI$1/;
554a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	s/ (.)/ \\fI$1/;
555a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner	$_ .= '\fR';
556a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    }
557a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner
558a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner    $_;
559a6dfe5f70959a596290e1591579d26a288a1a2f9David 'Digit' Turner}
560