From b3578fc9ffe70b9466687f9f6470a85f1a0ab14f Mon Sep 17 00:00:00 2001 From: Bernhard Voelker Date: Thu, 12 Sep 2013 00:02:33 +0200 Subject: maint: avoid patching help2man Commit cde1ea0e separated the coreutils-specific patches from help2man. Most changes had been made to accommodate to the coreutils style guide, i.e., to avoid syntax-check failures like sc_long_lines. Yet 2 changes had to be put into the patch help2man.diff. But this added the dependency to patch(1) in distribution builds. Incidentally, the 2 remaining parts of the patch can easily be done outside of help2man. Therefore, this commit partly reverts the recent separation of help2man into 'help2man.in' and 'help2man.diff', and instead uses the original help2man script. * man/help2man.in: Rename to ... * man/help2man: ... this file. * man/help2man.diff: Remove. * man/local.mk (mandeps): Remove man/help2man. (man/help2man): Remove recipe. (.x.1): Add the --info-page option when calling help2man in order to change the name of the texinfo manual from the default, "info PRG", to "info coreutils 'PRG invocation'". Furthermore, use an sed pattern to remove the sentence starting with "For complete documentation". * .gitignore (/man/help2man): Remove entry. * .x-update-copyright: Replace the entries for the files 'man/help2man.diff' and 'man/help2man.in' by 'man/help2man'. * cfg.mk (sc_long_lines): Instead of 'man/help2man.in', exempt 'man/help2man' from this test. (sc_po_check): Likewise. (sc_space_tab): Instead of 'man/help2man.diff', exempt 'man/help2man' from this test. (sc_trailing_blank): Likewise. (sc_prohibit_tab_based_indentation): Instead of 'man/help2man.in' and 'man/help2man.diff', exempt 'man/help2man'. * man/dummy-man: Recognize the option --info-page=... as no-op. --- man/dummy-man | 1 + man/help2man | 733 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ man/help2man.diff | 32 --- man/help2man.in | 733 ------------------------------------------------------ man/local.mk | 16 +- 5 files changed, 739 insertions(+), 776 deletions(-) create mode 100755 man/help2man delete mode 100644 man/help2man.diff delete mode 100755 man/help2man.in (limited to 'man') diff --git a/man/dummy-man b/man/dummy-man index 306937628..dca2b6784 100755 --- a/man/dummy-man +++ b/man/dummy-man @@ -30,6 +30,7 @@ while test $# -gt 0; do # in the makefile. --include=*);; --include) shift;; + --info-page=*);; -*) fatal_ "invalid or unrecognized help2man option '$1'";; --) shift; break;; *) break;; diff --git a/man/help2man b/man/help2man new file mode 100755 index 000000000..bfeb98972 --- /dev/null +++ b/man/help2man @@ -0,0 +1,733 @@ +#!/usr/bin/perl -w + +# Generate a short man page from --help and --version output. +# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, +# 2010, 2011, 2012, 2013 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 3, 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, see . + +# Written by Brendan O'Dea +# Available from ftp://ftp.gnu.org/gnu/help2man/ + +use 5.008; +use strict; +use Getopt::Long; +use Text::Tabs qw(expand); +use POSIX qw(strftime setlocale LC_ALL); + +my $this_program = 'help2man'; +my $this_version = '1.43.3'; + +sub _ { $_[0] } +sub configure_locale +{ + my $locale = shift; + die "$this_program: no locale support (Locale::gettext required)\n" + unless $locale eq 'C'; +} + +sub dec { $_[0] } +sub enc { $_[0] } +sub enc_user { $_[0] } +sub kark { die +(sprintf shift, @_), "\n" } +sub N_ { $_[0] } + +sub program_basename; +sub get_option_value; +sub convert_option; + +my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version; +GNU %s %s + +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, +2011, 2012, 2013 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. + +Written by Brendan O'Dea +EOT + +my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program; +`%s' generates a man page out of `--help' and `--version' output. + +Usage: %s [OPTION]... EXECUTABLE + + -n, --name=STRING description for the NAME paragraph + -s, --section=SECTION section number for manual page (1, 6, 8) + -m, --manual=TEXT name of manual (User Commands, ...) + -S, --source=TEXT source of program (FSF, Debian, ...) + -L, --locale=STRING select locale (default "C") + -i, --include=FILE include material from `FILE' + -I, --opt-include=FILE include material from `FILE' if it exists + -o, --output=FILE send output to `FILE' + -p, --info-page=TEXT name of Texinfo manual + -N, --no-info suppress pointer to Texinfo manual + -l, --libtool exclude the `lt-' from the program name + --help print this help, then exit + --version print version number, then exit + +EXECUTABLE should accept `--help' and `--version' options and produce output on +stdout although alternatives may be specified using: + + -h, --help-option=STRING help option string + -v, --version-option=STRING version option string + --version-string=STRING version string + --no-discard-stderr include stderr when parsing option output + +Report bugs to . +EOT + +my $section = 1; +my $manual = ''; +my $source = ''; +my $help_option = '--help'; +my $version_option = '--version'; +my $discard_stderr = 1; +my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool, + $version_text); + +my %opt_def = ( + 'n|name=s' => \$opt_name, + 's|section=s' => \$section, + 'm|manual=s' => \$manual, + 'S|source=s' => \$source, + 'L|locale=s' => sub { configure_locale pop }, + 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, + 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, + 'o|output=s' => \$opt_output, + 'p|info-page=s' => \$opt_info, + 'N|no-info' => \$opt_no_info, + 'l|libtool' => \$opt_libtool, + 'help' => sub { print $help_info; exit }, + 'version' => sub { print $version_info; exit }, + 'h|help-option=s' => \$help_option, + 'v|version-option=s' => \$version_option, + 'version-string=s' => \$version_text, + 'discard-stderr!' => \$discard_stderr, +); + +# Parse options. +Getopt::Long::config('bundling'); +die $help_info unless GetOptions %opt_def and @ARGV == 1; + +my %include = (); +my %replace = (); +my %append = (); +my %append_match = (); +my @include = (); # retain order given in include file + +# Process include file (if given). Format is: +# +# Optional initial text, ignored. May include lines starting with `-' +# which are processed as options. +# +# [section] +# Verbatim text to be included in the named section. By default at +# the start, but in the case of `name' and `synopsis' the content +# will replace the autogenerated contents. +# +# [section] +# Verbatim text to be appended to the end of the named section. +# +# /pattern/ +# Verbatim text for inclusion below a paragraph matching `pattern'. +# + +while (@opt_include) +{ + my ($inc, $required) = @{shift @opt_include}; + + next unless -f $inc or $required; + kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $! + unless open INC, $inc; + + my $key; + my $hash; + + while () + { + # Convert input to internal Perl format, so that multibyte + # sequences are treated as single characters. + $_ = dec $_; + + # [section] + if (/^\[([^]]+)\]\s*$/) + { + $key = uc $1; + $key =~ s/^\s+//; + $key =~ s/\s+$//; + $hash = \%include; + # Handle explicit [section] + if ($key =~ s/^([<>=])\s*//) + { + if ($1 eq '>') { $hash = \%append; } + elsif ($1 eq '=') { $hash = \%replace; } + } + # NAME/SYNOPSIS replace by default + elsif ($key eq _('NAME') or $key eq _('SYNOPSIS')) + { + $hash = \%replace; + } + else + { + $hash = \%include; + } + + push @include, $key + unless $include{$key} or $replace{$key} or $append{$key}; + + next; + } + + # /pattern/ + if (m!^/(.*)/([ims]*)\s*$!) + { + my $pat = $2 ? "(?$2)$1" : $1; + + # Check pattern. + eval { $key = qr($pat) }; + if ($@) + { + $@ =~ s/ at .*? line \d.*//; + die "$inc:$.:$@"; + } + + $hash = \%append_match; + next; + } + + # Check for options before the first section--anything else is + # silently ignored, allowing the first for comments and + # revision info. + unless ($key) + { + # handle options + if (/^-/) + { + local @ARGV = split; + GetOptions %opt_def; + } + + next; + } + + $hash->{$key} .= $_; + } + + close INC; + + kark N_("%s: no valid information found in `%s'"), $this_program, $inc + unless $key; +} + +# Compress trailing blank lines. +for my $hash (\(%include, %replace, %append, %append_match)) +{ + for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } +} + +# Grab help and version info from executable. +my $help_text = get_option_value $ARGV[0], $help_option; +$version_text ||= get_option_value $ARGV[0], $version_option; + +# Translators: the following message is a strftime(3) format string, which in +# the English version expands to the month as a word and the full year. It +# is used on the footer of the generated manual pages. If in doubt, you may +# just use %x as the value (which should be the full locale-specific date). +my $date = enc strftime _("%B %Y"), localtime; +my $program = program_basename $ARGV[0]; +my $package = $program; +my $version; + +if ($opt_output) +{ + unlink $opt_output or kark N_("%s: can't unlink %s (%s)"), + $this_program, $opt_output, $! if -e $opt_output; + + open STDOUT, ">$opt_output" + or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!; +} + +# The first line of the --version information is assumed to be in one +# of the following formats: +# +# +# +# {GNU,Free} +# ({GNU,Free} ) +# - {GNU,Free} +# +# and separated from any copyright/author details by a blank line. + +($_, $version_text) = ((split /\n+/, $version_text, 2), ''); + +if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or + /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) +{ + $program = program_basename $1; + $package = $2; + $version = $3; +} +elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) +{ + $program = program_basename $2; + $package = $1 ? "$1$program" : $program; + $version = $3; +} +else +{ + $version = $_; +} + +# No info for `info' itself. +$opt_no_info = 1 if $program eq 'info'; + +if ($opt_name) +{ + # --name overrides --include contents. + $replace{_('NAME')} = "$program \\- $opt_name\n"; +} + +# Translators: "NAME", "SYNOPSIS" and other one or two word strings in all +# upper case are manual page section headings. The man(1) manual page in your +# language, if available should provide the conventional translations. +for ($replace{_('NAME')} || ($include{_('NAME')} ||= '')) +{ + if ($_) # Use first name given as $program + { + $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/; + } + else # Set a default (useless) NAME paragraph. + { + $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program, + $program, $version; + } +} + +# Man pages traditionally have the page title in caps. +my $PROGRAM = uc $program; + +# Set default page head/footers +$source ||= "$program $version"; +unless ($manual) +{ + for ($section) + { + if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') } + elsif (/^6/) { $manual = enc _('Games') } + else { $manual = enc _('User Commands') } + } +} + +# Extract usage clause(s) [if any] for SYNOPSIS. +# Translators: "Usage" and "or" here are patterns (regular expressions) which +# are used to match the usage synopsis in program output. An example from cp +# (GNU coreutils) which contains both strings: +# Usage: cp [OPTION]... [-T] SOURCE DEST +# or: cp [OPTION]... SOURCE... DIRECTORY +# or: cp [OPTION]... -t DIRECTORY SOURCE... +my $PAT_USAGE = _('Usage'); +my $PAT_USAGE_CONT = _('or'); +if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om) +{ + my @syn = $3 . $4; + + if ($_ = $5) + { + s/^\n//; + for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ } + } + + my $synopsis = ''; + for (@syn) + { + $synopsis .= ".br\n" if $synopsis; + s!^\S*/!!; + s/^lt-// if $opt_libtool; + s/^(\S+) *//; + $synopsis .= ".B $1\n"; + s/\s+$//; + s/(([][]|\.\.+)+)/\\fR$1\\fI/g; + s/^/\\fI/ unless s/^\\fR//; + $_ .= '\fR'; + s/(\\fI)( *)/$2$1/g; + s/\\fI\\fR//g; + s/^\\fR//; + s/\\fI$//; + s/^\./\\&./; + + $synopsis .= "$_\n"; + } + + $include{_('SYNOPSIS')} .= $synopsis; +} + +# Process text, initial section is DESCRIPTION. +my $sect = _('DESCRIPTION'); +$_ = "$help_text\n\n$version_text"; + +# Normalise paragraph breaks. +s/^\n+//; +s/\n*$/\n/; +s/\n\n+/\n\n/g; + +# Join hyphenated lines. +s/([A-Za-z])-\n *([A-Za-z])/$1$2/g; + +# Temporarily exchange leading dots, apostrophes and backslashes for +# tokens. +s/^\./\x80/mg; +s/^'/\x81/mg; +s/\\/\x82/g; + +# Translators: patterns are used to match common program output. In the source +# these strings are all of the form of "my $PAT_something = _('...');" and are +# regular expressions. If there is more than one commonly used string, you +# may separate alternatives with "|". Spaces in these expressions are written +# as " +" to indicate that more than one space may be matched. The string +# "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an +# optional word, so that either "Report bugs" or "Report _program_ bugs" will +# be matched. +my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to'); +my $PAT_AUTHOR = _('Written +by'); +my $PAT_OPTIONS = _('Options'); +my $PAT_ENVIRONMENT = _('Environment'); +my $PAT_FILES = _('Files'); +my $PAT_EXAMPLES = _('Examples'); +my $PAT_FREE_SOFTWARE = _('This +is +free +software'); + +# Start a new paragraph (if required) for these. +s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og; + +# Convert iso-8859-1 copyright symbol or (c) to nroff +# character. +s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; + +while (length) +{ + # Convert some standard paragraph names. + if (s/^($PAT_OPTIONS): *\n//o) + { + $sect = _('OPTIONS'); + next; + } + if (s/^($PAT_ENVIRONMENT): *\n//o) + { + $sect = _('ENVIRONMENT'); + next; + } + if (s/^($PAT_FILES): *\n//o) + { + $sect = _('FILES'); + next; + } + elsif (s/^($PAT_EXAMPLES): *\n//o) + { + $sect = _('EXAMPLES'); + next; + } + + # Copyright section + if (/^Copyright /) + { + $sect = _('COPYRIGHT'); + } + + # Bug reporting section. + elsif (/^($PAT_BUGS) /o) + { + $sect = _('REPORTING BUGS'); + } + + # Author section. + elsif (/^($PAT_AUTHOR)/o) + { + $sect = _('AUTHOR'); + } + + # Examples, indicated by an indented leading $, % or > are + # rendered in a constant width font. + if (/^( +)([\$\%>] )\S/) + { + my $indent = $1; + my $prefix = $2; + my $break = '.IP'; + while (s/^$indent\Q$prefix\E(\S.*)\n*//) + { + $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; + $break = '.br'; + } + + next; + } + + my $matched = ''; + + # Sub-sections have a trailing colon and the second line indented. + if (s/^(\S.*:) *\n / /) + { + $matched .= $& if %append_match; + $include{$sect} .= qq(.SS "$1"\n); + } + + my $indent = 0; + my $content = ''; + + # Option with description. + if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//) + { + $matched .= $& if %append_match; + $indent = length ($4 || "$1$3"); + $content = ".TP\n\x84$2\n\x84$5\n"; + unless ($4) + { + # Indent may be different on second line. + $indent = length $& if /^ {20,}/; + } + } + + # Option without description. + elsif (s/^ {1,10}([+-]\S.*)\n//) + { + $matched .= $& if %append_match; + $content = ".HP\n\x84$1\n"; + $indent = 80; # not continued + } + + # Indented paragraph with tag. + elsif (s/^( +(\S.*?) +)(\S.*)\n//) + { + $matched .= $& if %append_match; + $indent = length $1; + $content = ".TP\n\x84$2\n\x84$3\n"; + } + + # Indented paragraph. + elsif (s/^( +)(\S.*)\n//) + { + $matched .= $& if %append_match; + $indent = length $1; + $content = ".IP\n\x84$2\n"; + } + + # Left justified paragraph. + else + { + s/(.*)\n//; + $matched .= $& if %append_match; + $content = ".PP\n" if $include{$sect}; + $content .= "$1\n"; + } + + # Append continuations. + while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//) + { + $matched .= $& if %append_match; + $content .= "\x84$1\n"; + } + + # Move to next paragraph. + s/^\n+//; + + for ($content) + { + # Leading dot and apostrophe protection. + s/\x84\./\x80/g; + s/\x84'/\x81/g; + s/\x84//g; + + # Examples should be verbatim. + unless ($sect eq _('EXAMPLES')) + { + # Convert options. + s/(^|[ (])(-[][\w=-]+)/$1 . convert_option $2/mge; + + # Italicise filenames: /a/b, $VAR/c/d, ~/e/f + s! + (^|[ (]) # space/punctuation before + ( + (?:\$\w+|~)? # leading variable, or tilde + (?:/\w(?:[\w.-]*\w)?)+ # path components + ) + ($|[ ,;.)]) # space/punctuation after + !$1\\fI$2\\fP$3!xmg; + } + + # Escape remaining hyphens. + s/-/\x83/g; + + if ($sect eq _('COPYRIGHT')) + { + # Insert line breaks before additional copyright messages + # and the disclaimer. + s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og; + } + elsif ($sect eq _('REPORTING BUGS')) + { + # Handle multi-line bug reporting sections of the form: + # + # Report bugs to + # GNU home page: + # ... + s/\n([[:upper:]])/\n.br\n$1/g; + } + } + + # Check if matched paragraph contains /pat/. + if (%append_match) + { + for my $pat (keys %append_match) + { + if ($matched =~ $pat) + { + $content .= ".PP\n" unless $append_match{$pat} =~ /^\./; + $content .= $append_match{$pat}; + } + } + } + + $include{$sect} .= $content; +} + +# Refer to the real documentation. +unless ($opt_no_info) +{ + my $info_page = $opt_info || $program; + + $sect = _('SEE ALSO'); + $include{$sect} .= ".PP\n" if $include{$sect}; + $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page; +The full documentation for +.B %s +is maintained as a Texinfo manual. If the +.B info +and +.B %s +programs are properly installed at your site, the command +.IP +.B info %s +.PP +should give you access to the complete manual. +EOT +} + +# Append additional text. +while (my ($sect, $text) = each %append) +{ + $include{$sect} .= $append{$sect}; +} + +# Replace sections. +while (my ($sect, $text) = each %replace) +{ + $include{$sect} = $replace{$sect}; +} + +# Output header. +print <$stderr`; + + unless ($value) + { + my $err = N_("%s: can't get `%s' info from %s%s"); + my $extra = $discard_stderr + ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr") + : ''; + + kark $err, $this_program, $opt, $prog, $extra; + } + + $value; +} + +# Convert option dashes to \- to stop nroff from hyphenating 'em, and +# embolden. Option arguments get italicised. +sub convert_option +{ + local $_ = '\fB' . shift; + + s/-/\x83/g; + unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) + { + s/=(.)/\\fR=\\fI$1/; + s/ (.)/ \\fI$1/; + $_ .= '\fR'; + } + + $_; +} diff --git a/man/help2man.diff b/man/help2man.diff deleted file mode 100644 index 12fa76f22..000000000 --- a/man/help2man.diff +++ /dev/null @@ -1,32 +0,0 @@ ---- man/help2man-orig -+++ man/help2man 2013-09-10 07:31:28.352365301 +0200 -@@ -412,6 +412,7 @@ - my $PAT_FILES = _('Files'); - my $PAT_EXAMPLES = _('Examples'); - my $PAT_FREE_SOFTWARE = _('This +is +free +software'); -+my $PAT_INFO = _('For +complete +documentation'); - - # Start a new paragraph (if required) for these. - s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og; -@@ -444,6 +445,12 @@ - next; - } - -+ # Skip any texinfo reference as that's handled separately -+ if (s/($PAT_INFO).*\n//o) -+ { -+ next; -+ } -+ - # Copyright section - if (/^Copyright /) - { -@@ -622,7 +629,7 @@ - .B %s - programs are properly installed at your site, the command - .IP --.B info %s -+.B info coreutils \(aq%s invocation\(aq - .PP - should give you access to the complete manual. - EOT diff --git a/man/help2man.in b/man/help2man.in deleted file mode 100755 index bfeb98972..000000000 --- a/man/help2man.in +++ /dev/null @@ -1,733 +0,0 @@ -#!/usr/bin/perl -w - -# Generate a short man page from --help and --version output. -# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, -# 2010, 2011, 2012, 2013 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 3, 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, see . - -# Written by Brendan O'Dea -# Available from ftp://ftp.gnu.org/gnu/help2man/ - -use 5.008; -use strict; -use Getopt::Long; -use Text::Tabs qw(expand); -use POSIX qw(strftime setlocale LC_ALL); - -my $this_program = 'help2man'; -my $this_version = '1.43.3'; - -sub _ { $_[0] } -sub configure_locale -{ - my $locale = shift; - die "$this_program: no locale support (Locale::gettext required)\n" - unless $locale eq 'C'; -} - -sub dec { $_[0] } -sub enc { $_[0] } -sub enc_user { $_[0] } -sub kark { die +(sprintf shift, @_), "\n" } -sub N_ { $_[0] } - -sub program_basename; -sub get_option_value; -sub convert_option; - -my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version; -GNU %s %s - -Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, -2011, 2012, 2013 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. - -Written by Brendan O'Dea -EOT - -my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program; -`%s' generates a man page out of `--help' and `--version' output. - -Usage: %s [OPTION]... EXECUTABLE - - -n, --name=STRING description for the NAME paragraph - -s, --section=SECTION section number for manual page (1, 6, 8) - -m, --manual=TEXT name of manual (User Commands, ...) - -S, --source=TEXT source of program (FSF, Debian, ...) - -L, --locale=STRING select locale (default "C") - -i, --include=FILE include material from `FILE' - -I, --opt-include=FILE include material from `FILE' if it exists - -o, --output=FILE send output to `FILE' - -p, --info-page=TEXT name of Texinfo manual - -N, --no-info suppress pointer to Texinfo manual - -l, --libtool exclude the `lt-' from the program name - --help print this help, then exit - --version print version number, then exit - -EXECUTABLE should accept `--help' and `--version' options and produce output on -stdout although alternatives may be specified using: - - -h, --help-option=STRING help option string - -v, --version-option=STRING version option string - --version-string=STRING version string - --no-discard-stderr include stderr when parsing option output - -Report bugs to . -EOT - -my $section = 1; -my $manual = ''; -my $source = ''; -my $help_option = '--help'; -my $version_option = '--version'; -my $discard_stderr = 1; -my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool, - $version_text); - -my %opt_def = ( - 'n|name=s' => \$opt_name, - 's|section=s' => \$section, - 'm|manual=s' => \$manual, - 'S|source=s' => \$source, - 'L|locale=s' => sub { configure_locale pop }, - 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, - 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, - 'o|output=s' => \$opt_output, - 'p|info-page=s' => \$opt_info, - 'N|no-info' => \$opt_no_info, - 'l|libtool' => \$opt_libtool, - 'help' => sub { print $help_info; exit }, - 'version' => sub { print $version_info; exit }, - 'h|help-option=s' => \$help_option, - 'v|version-option=s' => \$version_option, - 'version-string=s' => \$version_text, - 'discard-stderr!' => \$discard_stderr, -); - -# Parse options. -Getopt::Long::config('bundling'); -die $help_info unless GetOptions %opt_def and @ARGV == 1; - -my %include = (); -my %replace = (); -my %append = (); -my %append_match = (); -my @include = (); # retain order given in include file - -# Process include file (if given). Format is: -# -# Optional initial text, ignored. May include lines starting with `-' -# which are processed as options. -# -# [section] -# Verbatim text to be included in the named section. By default at -# the start, but in the case of `name' and `synopsis' the content -# will replace the autogenerated contents. -# -# [section] -# Verbatim text to be appended to the end of the named section. -# -# /pattern/ -# Verbatim text for inclusion below a paragraph matching `pattern'. -# - -while (@opt_include) -{ - my ($inc, $required) = @{shift @opt_include}; - - next unless -f $inc or $required; - kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $! - unless open INC, $inc; - - my $key; - my $hash; - - while () - { - # Convert input to internal Perl format, so that multibyte - # sequences are treated as single characters. - $_ = dec $_; - - # [section] - if (/^\[([^]]+)\]\s*$/) - { - $key = uc $1; - $key =~ s/^\s+//; - $key =~ s/\s+$//; - $hash = \%include; - # Handle explicit [section] - if ($key =~ s/^([<>=])\s*//) - { - if ($1 eq '>') { $hash = \%append; } - elsif ($1 eq '=') { $hash = \%replace; } - } - # NAME/SYNOPSIS replace by default - elsif ($key eq _('NAME') or $key eq _('SYNOPSIS')) - { - $hash = \%replace; - } - else - { - $hash = \%include; - } - - push @include, $key - unless $include{$key} or $replace{$key} or $append{$key}; - - next; - } - - # /pattern/ - if (m!^/(.*)/([ims]*)\s*$!) - { - my $pat = $2 ? "(?$2)$1" : $1; - - # Check pattern. - eval { $key = qr($pat) }; - if ($@) - { - $@ =~ s/ at .*? line \d.*//; - die "$inc:$.:$@"; - } - - $hash = \%append_match; - next; - } - - # Check for options before the first section--anything else is - # silently ignored, allowing the first for comments and - # revision info. - unless ($key) - { - # handle options - if (/^-/) - { - local @ARGV = split; - GetOptions %opt_def; - } - - next; - } - - $hash->{$key} .= $_; - } - - close INC; - - kark N_("%s: no valid information found in `%s'"), $this_program, $inc - unless $key; -} - -# Compress trailing blank lines. -for my $hash (\(%include, %replace, %append, %append_match)) -{ - for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } -} - -# Grab help and version info from executable. -my $help_text = get_option_value $ARGV[0], $help_option; -$version_text ||= get_option_value $ARGV[0], $version_option; - -# Translators: the following message is a strftime(3) format string, which in -# the English version expands to the month as a word and the full year. It -# is used on the footer of the generated manual pages. If in doubt, you may -# just use %x as the value (which should be the full locale-specific date). -my $date = enc strftime _("%B %Y"), localtime; -my $program = program_basename $ARGV[0]; -my $package = $program; -my $version; - -if ($opt_output) -{ - unlink $opt_output or kark N_("%s: can't unlink %s (%s)"), - $this_program, $opt_output, $! if -e $opt_output; - - open STDOUT, ">$opt_output" - or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!; -} - -# The first line of the --version information is assumed to be in one -# of the following formats: -# -# -# -# {GNU,Free} -# ({GNU,Free} ) -# - {GNU,Free} -# -# and separated from any copyright/author details by a blank line. - -($_, $version_text) = ((split /\n+/, $version_text, 2), ''); - -if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or - /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) -{ - $program = program_basename $1; - $package = $2; - $version = $3; -} -elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) -{ - $program = program_basename $2; - $package = $1 ? "$1$program" : $program; - $version = $3; -} -else -{ - $version = $_; -} - -# No info for `info' itself. -$opt_no_info = 1 if $program eq 'info'; - -if ($opt_name) -{ - # --name overrides --include contents. - $replace{_('NAME')} = "$program \\- $opt_name\n"; -} - -# Translators: "NAME", "SYNOPSIS" and other one or two word strings in all -# upper case are manual page section headings. The man(1) manual page in your -# language, if available should provide the conventional translations. -for ($replace{_('NAME')} || ($include{_('NAME')} ||= '')) -{ - if ($_) # Use first name given as $program - { - $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/; - } - else # Set a default (useless) NAME paragraph. - { - $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program, - $program, $version; - } -} - -# Man pages traditionally have the page title in caps. -my $PROGRAM = uc $program; - -# Set default page head/footers -$source ||= "$program $version"; -unless ($manual) -{ - for ($section) - { - if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') } - elsif (/^6/) { $manual = enc _('Games') } - else { $manual = enc _('User Commands') } - } -} - -# Extract usage clause(s) [if any] for SYNOPSIS. -# Translators: "Usage" and "or" here are patterns (regular expressions) which -# are used to match the usage synopsis in program output. An example from cp -# (GNU coreutils) which contains both strings: -# Usage: cp [OPTION]... [-T] SOURCE DEST -# or: cp [OPTION]... SOURCE... DIRECTORY -# or: cp [OPTION]... -t DIRECTORY SOURCE... -my $PAT_USAGE = _('Usage'); -my $PAT_USAGE_CONT = _('or'); -if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om) -{ - my @syn = $3 . $4; - - if ($_ = $5) - { - s/^\n//; - for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ } - } - - my $synopsis = ''; - for (@syn) - { - $synopsis .= ".br\n" if $synopsis; - s!^\S*/!!; - s/^lt-// if $opt_libtool; - s/^(\S+) *//; - $synopsis .= ".B $1\n"; - s/\s+$//; - s/(([][]|\.\.+)+)/\\fR$1\\fI/g; - s/^/\\fI/ unless s/^\\fR//; - $_ .= '\fR'; - s/(\\fI)( *)/$2$1/g; - s/\\fI\\fR//g; - s/^\\fR//; - s/\\fI$//; - s/^\./\\&./; - - $synopsis .= "$_\n"; - } - - $include{_('SYNOPSIS')} .= $synopsis; -} - -# Process text, initial section is DESCRIPTION. -my $sect = _('DESCRIPTION'); -$_ = "$help_text\n\n$version_text"; - -# Normalise paragraph breaks. -s/^\n+//; -s/\n*$/\n/; -s/\n\n+/\n\n/g; - -# Join hyphenated lines. -s/([A-Za-z])-\n *([A-Za-z])/$1$2/g; - -# Temporarily exchange leading dots, apostrophes and backslashes for -# tokens. -s/^\./\x80/mg; -s/^'/\x81/mg; -s/\\/\x82/g; - -# Translators: patterns are used to match common program output. In the source -# these strings are all of the form of "my $PAT_something = _('...');" and are -# regular expressions. If there is more than one commonly used string, you -# may separate alternatives with "|". Spaces in these expressions are written -# as " +" to indicate that more than one space may be matched. The string -# "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an -# optional word, so that either "Report bugs" or "Report _program_ bugs" will -# be matched. -my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to'); -my $PAT_AUTHOR = _('Written +by'); -my $PAT_OPTIONS = _('Options'); -my $PAT_ENVIRONMENT = _('Environment'); -my $PAT_FILES = _('Files'); -my $PAT_EXAMPLES = _('Examples'); -my $PAT_FREE_SOFTWARE = _('This +is +free +software'); - -# Start a new paragraph (if required) for these. -s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og; - -# Convert iso-8859-1 copyright symbol or (c) to nroff -# character. -s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; - -while (length) -{ - # Convert some standard paragraph names. - if (s/^($PAT_OPTIONS): *\n//o) - { - $sect = _('OPTIONS'); - next; - } - if (s/^($PAT_ENVIRONMENT): *\n//o) - { - $sect = _('ENVIRONMENT'); - next; - } - if (s/^($PAT_FILES): *\n//o) - { - $sect = _('FILES'); - next; - } - elsif (s/^($PAT_EXAMPLES): *\n//o) - { - $sect = _('EXAMPLES'); - next; - } - - # Copyright section - if (/^Copyright /) - { - $sect = _('COPYRIGHT'); - } - - # Bug reporting section. - elsif (/^($PAT_BUGS) /o) - { - $sect = _('REPORTING BUGS'); - } - - # Author section. - elsif (/^($PAT_AUTHOR)/o) - { - $sect = _('AUTHOR'); - } - - # Examples, indicated by an indented leading $, % or > are - # rendered in a constant width font. - if (/^( +)([\$\%>] )\S/) - { - my $indent = $1; - my $prefix = $2; - my $break = '.IP'; - while (s/^$indent\Q$prefix\E(\S.*)\n*//) - { - $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; - $break = '.br'; - } - - next; - } - - my $matched = ''; - - # Sub-sections have a trailing colon and the second line indented. - if (s/^(\S.*:) *\n / /) - { - $matched .= $& if %append_match; - $include{$sect} .= qq(.SS "$1"\n); - } - - my $indent = 0; - my $content = ''; - - # Option with description. - if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//) - { - $matched .= $& if %append_match; - $indent = length ($4 || "$1$3"); - $content = ".TP\n\x84$2\n\x84$5\n"; - unless ($4) - { - # Indent may be different on second line. - $indent = length $& if /^ {20,}/; - } - } - - # Option without description. - elsif (s/^ {1,10}([+-]\S.*)\n//) - { - $matched .= $& if %append_match; - $content = ".HP\n\x84$1\n"; - $indent = 80; # not continued - } - - # Indented paragraph with tag. - elsif (s/^( +(\S.*?) +)(\S.*)\n//) - { - $matched .= $& if %append_match; - $indent = length $1; - $content = ".TP\n\x84$2\n\x84$3\n"; - } - - # Indented paragraph. - elsif (s/^( +)(\S.*)\n//) - { - $matched .= $& if %append_match; - $indent = length $1; - $content = ".IP\n\x84$2\n"; - } - - # Left justified paragraph. - else - { - s/(.*)\n//; - $matched .= $& if %append_match; - $content = ".PP\n" if $include{$sect}; - $content .= "$1\n"; - } - - # Append continuations. - while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//) - { - $matched .= $& if %append_match; - $content .= "\x84$1\n"; - } - - # Move to next paragraph. - s/^\n+//; - - for ($content) - { - # Leading dot and apostrophe protection. - s/\x84\./\x80/g; - s/\x84'/\x81/g; - s/\x84//g; - - # Examples should be verbatim. - unless ($sect eq _('EXAMPLES')) - { - # Convert options. - s/(^|[ (])(-[][\w=-]+)/$1 . convert_option $2/mge; - - # Italicise filenames: /a/b, $VAR/c/d, ~/e/f - s! - (^|[ (]) # space/punctuation before - ( - (?:\$\w+|~)? # leading variable, or tilde - (?:/\w(?:[\w.-]*\w)?)+ # path components - ) - ($|[ ,;.)]) # space/punctuation after - !$1\\fI$2\\fP$3!xmg; - } - - # Escape remaining hyphens. - s/-/\x83/g; - - if ($sect eq _('COPYRIGHT')) - { - # Insert line breaks before additional copyright messages - # and the disclaimer. - s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og; - } - elsif ($sect eq _('REPORTING BUGS')) - { - # Handle multi-line bug reporting sections of the form: - # - # Report bugs to - # GNU home page: - # ... - s/\n([[:upper:]])/\n.br\n$1/g; - } - } - - # Check if matched paragraph contains /pat/. - if (%append_match) - { - for my $pat (keys %append_match) - { - if ($matched =~ $pat) - { - $content .= ".PP\n" unless $append_match{$pat} =~ /^\./; - $content .= $append_match{$pat}; - } - } - } - - $include{$sect} .= $content; -} - -# Refer to the real documentation. -unless ($opt_no_info) -{ - my $info_page = $opt_info || $program; - - $sect = _('SEE ALSO'); - $include{$sect} .= ".PP\n" if $include{$sect}; - $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page; -The full documentation for -.B %s -is maintained as a Texinfo manual. If the -.B info -and -.B %s -programs are properly installed at your site, the command -.IP -.B info %s -.PP -should give you access to the complete manual. -EOT -} - -# Append additional text. -while (my ($sect, $text) = each %append) -{ - $include{$sect} .= $append{$sect}; -} - -# Replace sections. -while (my ($sect, $text) = each %replace) -{ - $include{$sect} = $replace{$sect}; -} - -# Output header. -print <$stderr`; - - unless ($value) - { - my $err = N_("%s: can't get `%s' info from %s%s"); - my $extra = $discard_stderr - ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr") - : ''; - - kark $err, $this_program, $opt, $prog, $extra; - } - - $value; -} - -# Convert option dashes to \- to stop nroff from hyphenating 'em, and -# embolden. Option arguments get italicised. -sub convert_option -{ - local $_ = '\fB' . shift; - - s/-/\x83/g; - unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) - { - s/=(.)/\\fR=\\fI$1/; - s/ (.)/ \\fI$1/; - $_ .= '\fR'; - } - - $_; -} diff --git a/man/local.mk b/man/local.mk index d967d1636..266b780f9 100644 --- a/man/local.mk +++ b/man/local.mk @@ -50,9 +50,6 @@ distclean-local: # Dependencies common to all man pages. Updated below. mandeps = -# Depend on the help2man script. -mandeps += man/help2man - # Depend on this to get version number changes. mandeps += .version @@ -62,13 +59,6 @@ mandeps += $(top_srcdir)/src/system.h $(ALL_MANS): $(mandeps) -# Create help2man from the upstream version and out patch. -man/help2man: man/help2man.in man/help2man.diff - $(AM_V_GEN)cp man/help2man.in man/help2man.tmp \ - && VERSION_CONTROL=none patch man/help2man.tmp < man/help2man.diff \ - && chmod a+x man/help2man.tmp \ - && mv man/help2man.tmp man/help2man - # Most prog.1 man pages depend on src/prog. List the exceptions: # Note that dir and vdir are exceptions only if you consider the name # of the .c file upon which they depend: ls.c. @@ -200,7 +190,11 @@ man/yes.1: src/yes --source='$(PACKAGE_STRING)' \ --include=$(srcdir)/man/$$name.x \ --output=$$t/$$name.1 $$t/$$name \ - && sed 's|$*\.td/||g' $$t/$$name.1 > $@-t \ + --info-page='coreutils \(aq'$$name' invocation\(aq' \ + && sed \ + -e 's|$*\.td/||g' \ + -e '/For complete documentation/d' \ + $$t/$$name.1 > $@-t \ && rm -rf $$t \ && chmod a-w $@-t \ && mv $@-t $@ -- cgit v1.2.3-70-g09d2