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