17c478bd9Sstevel@tonic-gate#!/usr/bin/perl -w 27c478bd9Sstevel@tonic-gate 37c478bd9Sstevel@tonic-gate# Generate a short man page from --help and --version output. 47c478bd9Sstevel@tonic-gate# Copyright � 1997, 1998, 1999, 2000 Free Software Foundation, Inc. 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate# This program is free software; you can redistribute it and/or modify 77c478bd9Sstevel@tonic-gate# it under the terms of the GNU General Public License as published by 87c478bd9Sstevel@tonic-gate# the Free Software Foundation; either version 2, or (at your option) 97c478bd9Sstevel@tonic-gate# any later version. 107c478bd9Sstevel@tonic-gate 117c478bd9Sstevel@tonic-gate# This program is distributed in the hope that it will be useful, 127c478bd9Sstevel@tonic-gate# but WITHOUT ANY WARRANTY; without even the implied warranty of 137c478bd9Sstevel@tonic-gate# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147c478bd9Sstevel@tonic-gate# GNU General Public License for more details. 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate# You should have received a copy of the GNU General Public License 177c478bd9Sstevel@tonic-gate# along with this program; if not, write to the Free Software Foundation, 187c478bd9Sstevel@tonic-gate# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gate# Written by Brendan O'Dea <bod@compusol.com.au> 217c478bd9Sstevel@tonic-gate# Available from ftp://ftp.gnu.org/gnu/help2man/ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gateuse 5.004; 247c478bd9Sstevel@tonic-gateuse strict; 257c478bd9Sstevel@tonic-gateuse Getopt::Long; 267c478bd9Sstevel@tonic-gateuse Text::Tabs qw(expand); 277c478bd9Sstevel@tonic-gateuse POSIX qw(strftime setlocale LC_TIME); 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gatemy $this_program = 'help2man'; 307c478bd9Sstevel@tonic-gatemy $this_version = '1.23'; 317c478bd9Sstevel@tonic-gatemy $version_info = <<EOT; 327c478bd9Sstevel@tonic-gateGNU $this_program $this_version 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gateCopyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. 357c478bd9Sstevel@tonic-gateThis is free software; see the source for copying conditions. There is NO 367c478bd9Sstevel@tonic-gatewarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gateWritten by Brendan O'Dea <bod\@compusol.com.au> 397c478bd9Sstevel@tonic-gateEOT 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gatemy $help_info = <<EOT; 427c478bd9Sstevel@tonic-gate`$this_program' generates a man page out of `--help' and `--version' output. 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gateUsage: $this_program [OPTION]... EXECUTABLE 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate -n, --name=STRING use `STRING' as the description for the NAME paragraph 477c478bd9Sstevel@tonic-gate -s, --section=SECTION use `SECTION' as the section for the man page 487c478bd9Sstevel@tonic-gate -i, --include=FILE include material from `FILE' 497c478bd9Sstevel@tonic-gate -I, --opt-include=FILE include material from `FILE' if it exists 507c478bd9Sstevel@tonic-gate -o, --output=FILE send output to `FILE' 517c478bd9Sstevel@tonic-gate -N, --no-info suppress pointer to Texinfo manual 527c478bd9Sstevel@tonic-gate --help print this help, then exit 537c478bd9Sstevel@tonic-gate --version print version number, then exit 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gateEXECUTABLE should accept `--help' and `--version' options. 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gateReport bugs to <bug-help2man\@gnu.org>. 587c478bd9Sstevel@tonic-gateEOT 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gatemy $section = 1; 617c478bd9Sstevel@tonic-gatemy ($opt_name, @opt_include, $opt_output, $opt_no_info); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate# Parse options. 647c478bd9Sstevel@tonic-gateGetopt::Long::config('bundling'); 657c478bd9Sstevel@tonic-gateGetOptions ( 667c478bd9Sstevel@tonic-gate 'n|name=s' => \$opt_name, 677c478bd9Sstevel@tonic-gate 's|section=s' => \$section, 687c478bd9Sstevel@tonic-gate 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, 697c478bd9Sstevel@tonic-gate 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, 707c478bd9Sstevel@tonic-gate 'o|output=s' => \$opt_output, 717c478bd9Sstevel@tonic-gate 'N|no-info' => \$opt_no_info, 727c478bd9Sstevel@tonic-gate help => sub { print $help_info; exit }, 737c478bd9Sstevel@tonic-gate version => sub { print $version_info; exit }, 747c478bd9Sstevel@tonic-gate) or die $help_info; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gatedie $help_info unless @ARGV == 1; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gatemy %include = (); 797c478bd9Sstevel@tonic-gatemy %append = (); 807c478bd9Sstevel@tonic-gatemy @include = (); # retain order given in include file 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate# Provide replacement `quote-regex' operator for pre-5.005. 837c478bd9Sstevel@tonic-gateBEGIN { eval q(sub qr { '' =~ $_[0]; $_[0] }) if $] < 5.005 } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate# Process include file (if given). Format is: 867c478bd9Sstevel@tonic-gate# 877c478bd9Sstevel@tonic-gate# [section name] 887c478bd9Sstevel@tonic-gate# verbatim text 897c478bd9Sstevel@tonic-gate# 907c478bd9Sstevel@tonic-gate# or 917c478bd9Sstevel@tonic-gate# 927c478bd9Sstevel@tonic-gate# /pattern/ 937c478bd9Sstevel@tonic-gate# verbatim text 947c478bd9Sstevel@tonic-gate# 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gatefor (@opt_include) 977c478bd9Sstevel@tonic-gate{ 987c478bd9Sstevel@tonic-gate my ($inc, $required) = @$_; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate next unless -f $inc or $required; 1017c478bd9Sstevel@tonic-gate die "$this_program: can't open `$inc' ($!)\n" 1027c478bd9Sstevel@tonic-gate unless open INC, $inc; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate my $key; 1057c478bd9Sstevel@tonic-gate my $hash = \%include; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate while (<INC>) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate # [section] 1107c478bd9Sstevel@tonic-gate if (/^\[([^]]+)\]/) 1117c478bd9Sstevel@tonic-gate { 1127c478bd9Sstevel@tonic-gate $key = uc $1; 1137c478bd9Sstevel@tonic-gate $key =~ s/^\s+//; 1147c478bd9Sstevel@tonic-gate $key =~ s/\s+$//; 1157c478bd9Sstevel@tonic-gate $hash = \%include; 1167c478bd9Sstevel@tonic-gate push @include, $key unless $include{$key}; 1177c478bd9Sstevel@tonic-gate next; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate # /pattern/ 1217c478bd9Sstevel@tonic-gate if (m!^/(.*)/([ims]*)!) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate my $pat = $2 ? "(?$2)$1" : $1; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate # Check pattern. 1267c478bd9Sstevel@tonic-gate eval { $key = qr($pat) }; 1277c478bd9Sstevel@tonic-gate if ($@) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate $@ =~ s/ at .*? line \d.*//; 1307c478bd9Sstevel@tonic-gate die "$inc:$.:$@"; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate $hash = \%append; 1347c478bd9Sstevel@tonic-gate next; 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate # Silently ignore anything before the first 1387c478bd9Sstevel@tonic-gate # section--allows for comments and revision info. 1397c478bd9Sstevel@tonic-gate next unless $key; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate $hash->{$key} ||= ''; 1427c478bd9Sstevel@tonic-gate $hash->{$key} .= $_; 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate close INC; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate die "$this_program: no valid information found in `$inc'\n" 1487c478bd9Sstevel@tonic-gate unless $key; 1497c478bd9Sstevel@tonic-gate} 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate# Compress trailing blank lines. 1527c478bd9Sstevel@tonic-gatefor my $hash (\(%include, %append)) 1537c478bd9Sstevel@tonic-gate{ 1547c478bd9Sstevel@tonic-gate for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } 1557c478bd9Sstevel@tonic-gate} 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate# Turn off localisation of executable's ouput. 1587c478bd9Sstevel@tonic-gate@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate# Turn off localisation of date (for strftime). 1617c478bd9Sstevel@tonic-gatesetlocale LC_TIME, 'C'; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate# Grab help and version info from executable. 1647c478bd9Sstevel@tonic-gatemy ($help_text, $version_text) = map { 1657c478bd9Sstevel@tonic-gate join '', map { s/ +$//; expand $_ } `$ARGV[0] --$_ 2>/dev/null` 1667c478bd9Sstevel@tonic-gate or die "$this_program: can't get `--$_' info from $ARGV[0]\n" 1677c478bd9Sstevel@tonic-gate} qw(help version); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gatemy $date = strftime "%B %Y", localtime; 1707c478bd9Sstevel@tonic-gate(my $program = $ARGV[0]) =~ s!.*/!!; 1717c478bd9Sstevel@tonic-gatemy $package = $program; 1727c478bd9Sstevel@tonic-gatemy $version; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gateif ($opt_output) 1757c478bd9Sstevel@tonic-gate{ 1767c478bd9Sstevel@tonic-gate unlink $opt_output 1777c478bd9Sstevel@tonic-gate or die "$this_program: can't unlink $opt_output ($!)\n" 1787c478bd9Sstevel@tonic-gate if -e $opt_output; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate open STDOUT, ">$opt_output" 1817c478bd9Sstevel@tonic-gate or die "$this_program: can't create $opt_output ($!)\n"; 1827c478bd9Sstevel@tonic-gate} 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate# The first line of the --version information is assumed to be in one 1857c478bd9Sstevel@tonic-gate# of the following formats: 1867c478bd9Sstevel@tonic-gate# 1877c478bd9Sstevel@tonic-gate# <version> 1887c478bd9Sstevel@tonic-gate# <program> <version> 1897c478bd9Sstevel@tonic-gate# {GNU,Free} <program> <version> 1907c478bd9Sstevel@tonic-gate# <program> ({GNU,Free} <package>) <version> 1917c478bd9Sstevel@tonic-gate# <program> - {GNU,Free} <package> <version> 1927c478bd9Sstevel@tonic-gate# 1937c478bd9Sstevel@tonic-gate# and seperated from any copyright/author details by a blank line. 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate($_, $version_text) = split /\n+/, $version_text, 2; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gateif (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or 1987c478bd9Sstevel@tonic-gate /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) 1997c478bd9Sstevel@tonic-gate{ 2007c478bd9Sstevel@tonic-gate $program = $1; 2017c478bd9Sstevel@tonic-gate $package = $2; 2027c478bd9Sstevel@tonic-gate $version = $3; 2037c478bd9Sstevel@tonic-gate} 2047c478bd9Sstevel@tonic-gateelsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) 2057c478bd9Sstevel@tonic-gate{ 2067c478bd9Sstevel@tonic-gate $program = $2; 2077c478bd9Sstevel@tonic-gate $package = $1 ? "$1$2" : $2; 2087c478bd9Sstevel@tonic-gate $version = $3; 2097c478bd9Sstevel@tonic-gate} 2107c478bd9Sstevel@tonic-gateelse 2117c478bd9Sstevel@tonic-gate{ 2127c478bd9Sstevel@tonic-gate $version = $_; 2137c478bd9Sstevel@tonic-gate} 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate$program =~ s!.*/!!; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate# No info for `info' itself. 2187c478bd9Sstevel@tonic-gate$opt_no_info = 1 if $program eq 'info'; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate# --name overrides --include contents. 2217c478bd9Sstevel@tonic-gate$include{NAME} = "$program \\- $opt_name\n" if $opt_name; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate# Default (useless) NAME paragraph. 2247c478bd9Sstevel@tonic-gate$include{NAME} ||= "$program \\- manual page for $program $version\n"; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate# Man pages traditionally have the page title in caps. 2277c478bd9Sstevel@tonic-gatemy $PROGRAM = uc $program; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate# Extract usage clause(s) [if any] for SYNOPSIS. 2307c478bd9Sstevel@tonic-gateif ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m) 2317c478bd9Sstevel@tonic-gate{ 2327c478bd9Sstevel@tonic-gate my @syn = $2 . $3; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate if ($_ = $4) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate s/^\n//; 2377c478bd9Sstevel@tonic-gate for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate my $synopsis = ''; 2417c478bd9Sstevel@tonic-gate for (@syn) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate $synopsis .= ".br\n" if $synopsis; 2447c478bd9Sstevel@tonic-gate s!^\S*/!!; 2457c478bd9Sstevel@tonic-gate s/^(\S+) *//; 2467c478bd9Sstevel@tonic-gate $synopsis .= ".B $1\n"; 2477c478bd9Sstevel@tonic-gate s/\s+$//; 2487c478bd9Sstevel@tonic-gate s/(([][]|\.\.+)+)/\\fR$1\\fI/g; 2497c478bd9Sstevel@tonic-gate s/^/\\fI/ unless s/^\\fR//; 2507c478bd9Sstevel@tonic-gate $_ .= '\fR'; 2517c478bd9Sstevel@tonic-gate s/(\\fI)( *)/$2$1/g; 2527c478bd9Sstevel@tonic-gate s/\\fI\\fR//g; 2537c478bd9Sstevel@tonic-gate s/^\\fR//; 2547c478bd9Sstevel@tonic-gate s/\\fI$//; 2557c478bd9Sstevel@tonic-gate s/^\./\\&./; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate $synopsis .= "$_\n"; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate $include{SYNOPSIS} ||= $synopsis; 2617c478bd9Sstevel@tonic-gate} 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate# Process text, initial section is DESCRIPTION. 2647c478bd9Sstevel@tonic-gatemy $sect = 'DESCRIPTION'; 2657c478bd9Sstevel@tonic-gate$_ = "$help_text\n\n$version_text"; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate# Normalise paragraph breaks. 2687c478bd9Sstevel@tonic-gates/^\n+//; 2697c478bd9Sstevel@tonic-gates/\n*$/\n/; 2707c478bd9Sstevel@tonic-gates/\n\n+/\n\n/g; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate# Temporarily exchange leading dots, apostrophes and backslashes for 2737c478bd9Sstevel@tonic-gate# tokens. 2747c478bd9Sstevel@tonic-gates/^\./\x80/mg; 2757c478bd9Sstevel@tonic-gates/^'/\x81/mg; 2767c478bd9Sstevel@tonic-gates/\\/\x82/g; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate# Start a new paragraph (if required) for these. 2797c478bd9Sstevel@tonic-gates/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gatesub convert_option; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gatewhile (length) 2847c478bd9Sstevel@tonic-gate{ 2857c478bd9Sstevel@tonic-gate # Convert some standard paragraph names. 2867c478bd9Sstevel@tonic-gate if (s/^(Options|Examples): *\n//) 2877c478bd9Sstevel@tonic-gate { 2887c478bd9Sstevel@tonic-gate $sect = uc $1; 2897c478bd9Sstevel@tonic-gate next; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate # Copyright section 2937c478bd9Sstevel@tonic-gate if (/^Copyright +[(\xa9]/) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate $sect = 'COPYRIGHT'; 2967c478bd9Sstevel@tonic-gate $include{$sect} ||= ''; 2977c478bd9Sstevel@tonic-gate $include{$sect} .= ".PP\n" if $include{$sect}; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate my $copy; 3007c478bd9Sstevel@tonic-gate ($copy, $_) = split /\n\n/, $_, 2; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate for ($copy) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate # Add back newline 3057c478bd9Sstevel@tonic-gate s/\n*$/\n/; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate # Convert iso9959-1 copyright symbol or (c) to nroff 3087c478bd9Sstevel@tonic-gate # character. 3097c478bd9Sstevel@tonic-gate s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate # Insert line breaks before additional copyright messages 3127c478bd9Sstevel@tonic-gate # and the disclaimer. 3137c478bd9Sstevel@tonic-gate s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate # Join hyphenated lines. 3167c478bd9Sstevel@tonic-gate s/([A-Za-z])-\n */$1/g; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate $include{$sect} .= $copy; 3207c478bd9Sstevel@tonic-gate $_ ||= ''; 3217c478bd9Sstevel@tonic-gate next; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate # Catch bug report text. 3257c478bd9Sstevel@tonic-gate if (/^(Report +bugs|Email +bug +reports +to) /) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate $sect = 'REPORTING BUGS'; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate # Author section. 3317c478bd9Sstevel@tonic-gate elsif (/^Written +by/) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate $sect = 'AUTHOR'; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate # Examples, indicated by an indented leading $, % or > are 3377c478bd9Sstevel@tonic-gate # rendered in a constant width font. 3387c478bd9Sstevel@tonic-gate if (/^( +)([\$\%>] )\S/) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate my $indent = $1; 3417c478bd9Sstevel@tonic-gate my $prefix = $2; 3427c478bd9Sstevel@tonic-gate my $break = '.IP'; 3437c478bd9Sstevel@tonic-gate $include{$sect} ||= ''; 3447c478bd9Sstevel@tonic-gate while (s/^$indent\Q$prefix\E(\S.*)\n*//) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; 3477c478bd9Sstevel@tonic-gate $break = '.br'; 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate next; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate my $matched = ''; 3547c478bd9Sstevel@tonic-gate $include{$sect} ||= ''; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate # Sub-sections have a trailing colon and the second line indented. 3577c478bd9Sstevel@tonic-gate if (s/^(\S.*:) *\n / /) 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate $matched .= $& if %append; 3607c478bd9Sstevel@tonic-gate $include{$sect} .= qq(.SS "$1"\n); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate my $indent = 0; 3647c478bd9Sstevel@tonic-gate my $content = ''; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate # Option with description. 3677c478bd9Sstevel@tonic-gate if (s/^( {1,10}([+-]\S.*?))(?:( +)|\n( {20,}))(\S.*)\n//) 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate $matched .= $& if %append; 3707c478bd9Sstevel@tonic-gate $indent = length ($4 || "$1$3"); 3717c478bd9Sstevel@tonic-gate $content = ".TP\n\x83$2\n\x83$5\n"; 3727c478bd9Sstevel@tonic-gate unless ($4) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate # Indent may be different on second line. 3757c478bd9Sstevel@tonic-gate $indent = length $& if /^ {20,}/; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate # Option without description. 3807c478bd9Sstevel@tonic-gate elsif (s/^ {1,10}([+-]\S.*)\n//) 3817c478bd9Sstevel@tonic-gate { 3827c478bd9Sstevel@tonic-gate $matched .= $& if %append; 3837c478bd9Sstevel@tonic-gate $content = ".HP\n\x83$1\n"; 3847c478bd9Sstevel@tonic-gate $indent = 80; # not continued 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate # Indented paragraph with tag. 3887c478bd9Sstevel@tonic-gate elsif (s/^( +(\S.*?) +)(\S.*)\n//) 3897c478bd9Sstevel@tonic-gate { 3907c478bd9Sstevel@tonic-gate $matched .= $& if %append; 3917c478bd9Sstevel@tonic-gate $indent = length $1; 3927c478bd9Sstevel@tonic-gate $content = ".TP\n\x83$2\n\x83$3\n"; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate # Indented paragraph. 3967c478bd9Sstevel@tonic-gate elsif (s/^( +)(\S.*)\n//) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate $matched .= $& if %append; 3997c478bd9Sstevel@tonic-gate $indent = length $1; 4007c478bd9Sstevel@tonic-gate $content = ".IP\n\x83$2\n"; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate # Left justified paragraph. 4047c478bd9Sstevel@tonic-gate else 4057c478bd9Sstevel@tonic-gate { 4067c478bd9Sstevel@tonic-gate s/(.*)\n//; 4077c478bd9Sstevel@tonic-gate $matched .= $& if %append; 4087c478bd9Sstevel@tonic-gate $content = ".PP\n" if $include{$sect}; 4097c478bd9Sstevel@tonic-gate $content .= "$1\n"; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate # Append continuations. 4137c478bd9Sstevel@tonic-gate while (s/^ {$indent}(\S.*)\n//) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate $matched .= $& if %append; 4167c478bd9Sstevel@tonic-gate $content .= "\x83$1\n" 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate # Move to next paragraph. 4207c478bd9Sstevel@tonic-gate s/^\n+//; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate for ($content) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate # Leading dot and apostrophe protection. 4257c478bd9Sstevel@tonic-gate s/\x83\./\x80/g; 4267c478bd9Sstevel@tonic-gate s/\x83'/\x81/g; 4277c478bd9Sstevel@tonic-gate s/\x83//g; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate # Convert options. 4307c478bd9Sstevel@tonic-gate s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge; 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate # Check if matched paragraph contains /pat/. 4347c478bd9Sstevel@tonic-gate if (%append) 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate for my $pat (keys %append) 4377c478bd9Sstevel@tonic-gate { 4387c478bd9Sstevel@tonic-gate if ($matched =~ $pat) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate $content .= ".PP\n" unless $append{$pat} =~ /^\./; 4417c478bd9Sstevel@tonic-gate $content .= $append{$pat}; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate $include{$sect} .= $content; 4477c478bd9Sstevel@tonic-gate} 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate# Refer to the real documentation. 4507c478bd9Sstevel@tonic-gateunless ($opt_no_info) 4517c478bd9Sstevel@tonic-gate{ 4527c478bd9Sstevel@tonic-gate $sect = 'SEE ALSO'; 4537c478bd9Sstevel@tonic-gate $include{$sect} ||= ''; 4547c478bd9Sstevel@tonic-gate $include{$sect} .= ".PP\n" if $include{$sect}; 4557c478bd9Sstevel@tonic-gate $include{$sect} .= <<EOT; 4567c478bd9Sstevel@tonic-gateThe full documentation for 4577c478bd9Sstevel@tonic-gate.B $program 4587c478bd9Sstevel@tonic-gateis maintained as a Texinfo manual. If the 4597c478bd9Sstevel@tonic-gate.B info 4607c478bd9Sstevel@tonic-gateand 4617c478bd9Sstevel@tonic-gate.B $program 4627c478bd9Sstevel@tonic-gateprograms are properly installed at your site, the command 4637c478bd9Sstevel@tonic-gate.IP 4647c478bd9Sstevel@tonic-gate.B info $program 4657c478bd9Sstevel@tonic-gate.PP 4667c478bd9Sstevel@tonic-gateshould give you access to the complete manual. 4677c478bd9Sstevel@tonic-gateEOT 4687c478bd9Sstevel@tonic-gate} 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate# Output header. 4717c478bd9Sstevel@tonic-gateprint <<EOT; 4727c478bd9Sstevel@tonic-gate.\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version. 4737c478bd9Sstevel@tonic-gate.TH $PROGRAM "$section" "$date" "$package $version" FSF 4747c478bd9Sstevel@tonic-gateEOT 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate# Section ordering. 4777c478bd9Sstevel@tonic-gatemy @pre = qw(NAME SYNOPSIS DESCRIPTION OPTIONS EXAMPLES); 4787c478bd9Sstevel@tonic-gatemy @post = ('AUTHOR', 'REPORTING BUGS', 'COPYRIGHT', 'SEE ALSO'); 4797c478bd9Sstevel@tonic-gatemy $filter = join '|', @pre, @post; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate# Output content. 4827c478bd9Sstevel@tonic-gatefor (@pre, (grep ! /^($filter)$/o, @include), @post) 4837c478bd9Sstevel@tonic-gate{ 4847c478bd9Sstevel@tonic-gate if ($include{$_}) 4857c478bd9Sstevel@tonic-gate { 4867c478bd9Sstevel@tonic-gate my $quote = /\W/ ? '"' : ''; 4877c478bd9Sstevel@tonic-gate print ".SH $quote$_$quote\n"; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate for ($include{$_}) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate # Replace leading dot, apostrophe and backslash tokens. 4927c478bd9Sstevel@tonic-gate s/\x80/\\&./g; 4937c478bd9Sstevel@tonic-gate s/\x81/\\&'/g; 4947c478bd9Sstevel@tonic-gate s/\x82/\\e/g; 4957c478bd9Sstevel@tonic-gate print; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate} 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gateexit; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate# Convert option dashes to \- to stop nroff from hyphenating 'em, and 5037c478bd9Sstevel@tonic-gate# embolden. Option arguments get italicised. 5047c478bd9Sstevel@tonic-gatesub convert_option 5057c478bd9Sstevel@tonic-gate{ 5067c478bd9Sstevel@tonic-gate local $_ = '\fB' . shift; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate s/-/\\-/g; 5097c478bd9Sstevel@tonic-gate unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate s/=(.)/\\fR=\\fI$1/; 5127c478bd9Sstevel@tonic-gate s/ (.)/ \\fI$1/; 5137c478bd9Sstevel@tonic-gate $_ .= '\fR'; 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate $_; 5177c478bd9Sstevel@tonic-gate} 518