diff options
Diffstat (limited to 'man/help2man')
-rwxr-xr-x | man/help2man | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/man/help2man b/man/help2man new file mode 100755 index 000000000..cf496211a --- /dev/null +++ b/man/help2man @@ -0,0 +1,382 @@ +#!/usr/bin/perl -w + +# Generate a short man page from --help and --version output. +# Copyright © 1997, 98 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Written by Brendan O'Dea <bod@compusol.com.au> +# and François Pinard <pinard@IRO.UMontreal.CA> + +require 5.003; + +use strict; +use Getopt::Long; +use POSIX 'strftime'; + +my $RCS_Id = '$Id: help2man,v 1.1 1998/09/09 13:47:43 meyering Exp $'; +my $this_program = 'help2man'; +my $this_version = '0.0'; + +if ($RCS_Id =~ /\$Id:\s+(\S+)\s+(\S+)/) +{ + $this_version = $2; + ($this_program = $1) =~ s/(\.\w+)?,v$//; +} + +my $version_info = <<EOT; +$this_program $this_version + +Copyright (C) 1997, 98 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +EOT + +my $help_info = <<EOT; +`$this_program' generates a man page out of `--help' and `--version' output. + +Usage: $this_program [OPTION]... EXECUTABLE + + --name=STRING use `STRING' as the description for the NAME paragraph + --include=FILE include material from `FILE' + --opt-include=FILE include material from `FILE' if it exists + --output=FILE send output to `FILE' + --help print this help, then exit + --version print $this_program program version number, then exit + +EXECUTABLE should accept `--help' and `version' options. +EOT + +my ($include, $opt_name, $opt_include, $opt_output, $opt_help, + $opt_version); + +# Parse options. +GetOptions ( + 'name=s' => \$opt_name, + 'include=s' => \$include, + 'opt-include=s' => \$opt_include, + 'output=s' => \$opt_output, + help => sub { print $help_info; exit }, + version => sub { print $version_info; exit }, +) or die $help_info; + +die $help_info unless @ARGV == 1; + +my %include = (); +my @include = (); # to retain order + +# Process include file (if given). Format is: +# +# [section name] +# verbatim text + +if ($include or $opt_include) +{ + if (open INC, $include || $opt_include) + { + my $sect; + + while (<INC>) + { + if (/^\[([^]]+)\]/) + { + $sect = uc $1; + $sect =~ s/^\s+//; + $sect =~ s/\s+$//; + next; + } + + # Silently ignore anything before the first + # section--allows for comments and revision info. + next unless $sect; + + push @include, $sect unless $include{$sect}; + $include{$sect} ||= ''; + $include{$sect} .= $_; + } + + close INC; + + die "$this_program: no valid information found in `$include'\n" + unless %include; + + # Compress trailing blank lines + for (keys %include) + { + $include{$_} =~ s/\n+$//; + $include{$_} .= "\n" unless /^NAME$/; + } + } + else + { + die "$this_program: can't open `$include' ($!)\n" if $include; + } +} + +# Turn off localisation of executable's ouput. +@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; + +# Grab help and version paragraphs from executable +my @help = split /\n\n+/, `$ARGV[0] --manhelp 2>/dev/null`; +my @version = split /\n\n+/, `$ARGV[0] --version 2>/dev/null` + or die "$this_program: can't get `--version' info from $ARGV[0]\n"; + +@help = split /\n\n+/, `$ARGV[0] --help 2>/dev/null` + or die "$this_program: can't get `--help' info from $ARGV[0]\n" + unless @help; + +my $date = strftime "%B %Y", localtime; +(my $program = $ARGV[0]) =~ s!.*/!!; +my $package = $program; +my $version; + +if ($opt_output) +{ + unlink $opt_output + or die "$this_program: can't unlink $opt_output ($!)\n" + if -e $opt_output; + + open STDOUT, ">$opt_output" + or die "$this_program: can't create $opt_output ($!)\n"; +} + +# The first line of the --version information is assumed to be in one +# of the following formats: +# +# <version> +# <program> <version> +# GNU <program> <version> +# <program> (GNU <package>) <version> +# <program> - GNU <package> <version> +# +# and seperated from any copyright/author details by a blank line. + +$_ = shift @version; + +if (/^(\S+)\s+\((GNU\s+[^)]+)\)\s+(.*)/ or + /^(\S+)\s+-\s*(GNU\s+\S+)\s+(.*)/) +{ + $program = $1; + $package = $2; + $version = $3; +} +elsif (/^(GNU\s+)?(\S+)\s+(.*)/) +{ + $program = $2; + $package = $1 ? "$1$2" : $2; + $version = $3; +} +else +{ + $version = $_; +} + +$program =~ s!.*/!!; + +# Check for name in help output +if ($help[0] =~ s/^(?:name|oneliner):\s*(\S.*)//) +{ + ($include{NAME} = "$program \\- $1") =~ s/\s+$//; + shift @help unless length $help[0]; +} + +# --name overrides --include contents and/or --manhelp oneliner +$include{NAME} = "$program \\- $opt_name" if $opt_name; + +# Default (useless) NAME paragraph +$include{NAME} ||= "$program \\- manual page for $program $version"; + +# Man pages traditionally have the page title in caps. +my $PROGRAM = uc $program; + +# Header. +print <<EOT; +.\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version. +.TH $PROGRAM 1 "$date" "$package $version" "FSF" +.SH NAME +$include{NAME} +EOT + +my $accumulate = 1; +my @description = (); + +sub convert_option; + +# Output converted --help information. +for (@help) +{ + chomp; + + if (s/^Usage:\s+\S+\s+(.*)\n?//) + { + # Turn the usage clause into a synopsis. + my $synopsis = ''; + + do { + my $syn = $1; + $syn =~ s/(([][]|\.\.+)+)/\\fR$1\\fI/g; + $syn =~ s/^/\\fI/ unless $syn =~ s/^\\fR//; + $syn .= '\fR'; + $syn =~ s/\\fI(\s*)\\fR/$1/g; + + $synopsis .= ".br\n" unless $accumulate; + $synopsis .= ".B $program\n"; + $synopsis .= "$syn\n"; + $accumulate = 0; + } while s/^(?:Usage|\s*or):\s+\S+\s+(.*)\n?//; + + # Include file overrides SYNOPSIS + print ".SH SYNOPSIS\n", $include{SYNOPSIS} || $synopsis; + + # Dump any accumulated description text. + print ".SH DESCRIPTION\n"; + print @description; + + # Add additional description text from include file + if ($include{DESCRIPTION}) + { + print ".PP\n" unless $include{DESCRIPTION} =~ /^\..P/; + print $include{DESCRIPTION}; + } + + next unless $_; + } + + # Accumulate text if the synopsis has not been produced yet. + if ($accumulate) + { + push @description, ".PP\n" if @description; + push @description, "$_\n"; + next; + } + + # Catch start of options. + if (/^Options:/) + { + print qq(.SH OPTIONS\n); + s/Options://; + } + + # Catch bug report text. + if (/^Report bugs |^Email bug reports to /) + { + print qq(.SH "REPORTING BUGS"\n$_\n); + next; + } + + # Special case for tar 1.12: --label=NAME\nPATTERN. + s{(\n[ \t]*)(-V,[ \t]+--label=NAME.*)\n[ \t]+PATTERN[ \t]+} + {$1$2$1\\&...=PATTERN }; + + # Convert options. + s/(\s)(-[][\w=-]+|\\&\S+)/$1 . convert_option $2/ge; + + # Option subsections have second line indented. + print qq(.SS "$1"\n) if s/^(\S.*)\n(\s)/$2/; + + # Lines indented more than about 10 spaces may be assumed to be + # continuations of the previous line. + s/\n {10,}/ /g; + + # Lines following dotted (*) or numbered points may also be + # continued if indented to the same level as the text following + # the point. + 1 while s{((?:^|\n)(\s+)(?:[1-9][.)]|\*)(\s+)(?:[^\n]+))\n\2 \3(\S)} + {$1 $4}g; + + # Indented paragraph. + if (/^\s/) + { + for (split /\n/) + { + s/^\s+//; + s/([^,])\s+/$1\n/; + print ".TP\n$_\n" if $_; + } + } + # Anything else. + else + { + print ".PP\n$_\n"; + } +} + +# Print any include items other than the ones we have already dealt +# with. +for (@include) +{ + print qq(.SH "$_"\n$include{$_}) + unless /^(NAME|SYNOPSIS|DESCRIPTION|SEE ALSO)$/; +} + +# Refer to the real documentation. +if ($include{'SEE ALSO'} or $program ne 'info') +{ + print qq(.SH "SEE ALSO"\n); + print $include{'SEE ALSO'}, ".PP\n" if $include{'SEE ALSO'}; + + print <<EOT unless $program eq 'info'; +The full documentation for +.B $program +is maintained as a Texinfo manual. If the +.B info +and +.B $program +programs are properly installed at your site, the command +.IP +.B info $program +.PP +should give you access to the complete manual. +EOT +} + +# Output converted --version information. +for (@version) +{ + chomp; + + # Convert copyright symbol or (c) to nroff character + s/Copyright\s+(?:\xa9|\([Cc]\))/Copyright \\(co/g; + + # Insert appropriate headings for copyright and author + if (/^Copyright\s\\/) { print ".SH COPYRIGHT\n" } + elsif (/^Written\s+by/) { print ".SH AUTHOR\n" } + else { print ".PP\n"; } + + # Insert line breaks before additional copyright messages and the + # disclaimer + s/(.)\n(Copyright\s|This is free software)/$1\n.br\n$2/g; + + print "$_\n"; +} + +exit; + +# Convert option dashes to \- to stop nroff from hyphenating 'em, and +# embolden. Option arguments get italicised. +sub convert_option +{ + my $option = '\fB' . shift; + + $option =~ s/-/\\-/g; + unless ($option =~ s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) + { + $option =~ s/=(.)/\\fR=\\fI$1/; + $option =~ s/ (.)/ \\fI$1/; + $option .= '\fR'; + } + + $option; +} |