4 # Self extracting help2man script.
6 # -q, --quiet Suppress extraction message
7 # -s, --stdout Extract to stdout
8 # -w, --with-gettext Add support for localized man pages
9 # -n, --name Print name only*
10 # -v, --version Print version only*
19 my ($program, $version) = ('help2man', '1.40.13');
22 die "Usage: $0 [--quiet] [--stdout] [--with-gettext] [--name] [--version]\n"
23 unless GetOptions \%opts, qw(quiet stdout with-gettext name version)
26 print "$program\n" if $opts{name};
27 print "$version\n" if $opts{version};
28 exit if $opts{name} or $opts{version};
40 $target =~ s/\.PL$// or die "$0: can't determine target name\n";
41 $tmp = "$target.tmp$$";
42 unlink $tmp or die "$0: can't unlink $tmp ($!)\n" if -e $tmp;
43 open OUT, ">$tmp" or die "$0: can't create $tmp ($!)\n";
46 print "Extracting $target (with variable substitutions)\n"
50 print OUT "$Config{startperl} -w\n";
52 # For systems without the crash-bang hack also add:
53 print OUT <<"!GROK!THIS!" if $Config{sharpbang} !~ /^#!/;
54 eval 'exec $Config{perlpath} -wS \$0 \${1+"\$@"}'
55 if \$running_under_some_shell;
57 \$running_under_some_shell = 0; # for -w
60 # No substitutions for this chunk:
61 print OUT <<'!NO!SUBS!';
63 # Generate a short man page from --help and --version output.
64 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
65 # 2010, 2011, 2012 Free Software Foundation, Inc.
67 # This program is free software; you can redistribute it and/or modify
68 # it under the terms of the GNU General Public License as published by
69 # the Free Software Foundation; either version 3, or (at your option)
72 # This program is distributed in the hope that it will be useful,
73 # but WITHOUT ANY WARRANTY; without even the implied warranty of
74 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75 # GNU General Public License for more details.
77 # You should have received a copy of the GNU General Public License
78 # along with this program; if not, see <http://www.gnu.org/licenses/>.
80 # Written by Brendan O'Dea <bod@debian.org>
81 # Available from ftp://ftp.gnu.org/gnu/help2man/
86 use Text::Tabs qw(expand);
87 use POSIX qw(strftime setlocale LC_ALL);
90 print OUT <<'!NO!SUBS!' if $opts{'with-gettext'};
92 use Encode qw(decode encode);
93 use I18N::Langinfo qw(langinfo CODESET);
96 # Interpolate program name and version:
97 print OUT <<"!GROK!THIS!";
99 my \$this_program = '$program';
100 my \$this_version = '$version';
103 # Conditionally include gettext support:
104 print OUT $opts{'with-gettext'} ? <<'!WITH!GETTEXT!' : <<'!NO!GETTEXT!';
108 my $gettext = Locale::gettext->domain($this_program);
109 sub _ { $gettext->get($_[0]) }
111 my ($user_locale) = grep defined && length,
112 (map $ENV{$_}, qw(LANGUAGE LC_ALL LC_MESSAGES LANG)), 'C';
114 my $user_encoding = langinfo CODESET;
116 # Set localisation of date and executable's output.
119 delete @ENV{qw(LANGUAGE LC_MESSAGES LANG)};
120 setlocale LC_ALL, $ENV{LC_ALL} = shift || 'C';
121 $encoding = langinfo CODESET;
124 sub dec { $encoding ? decode $encoding, $_[0] : $_[0] }
125 sub enc { $encoding ? encode $encoding, $_[0] : $_[0] }
126 sub enc_user { encode $user_encoding, $_[0] }
127 sub kark # die with message formatted in the invoking user's locale
129 setlocale LC_ALL, $user_locale;
130 my $fmt = $gettext->get(shift);
131 my $errmsg = enc_user sprintf $fmt, @_;
142 die "$this_program: no locale support (Locale::gettext required)\n"
143 unless $locale eq 'C';
148 sub enc_user { $_[0] }
149 sub kark { die +(sprintf shift, @_), "\n" }
152 # No substitutions for this chunk:
153 print OUT <<'!NO!SUBS!';
156 my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
159 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010,
160 2011, 2012 Free Software Foundation, Inc.
161 This is free software; see the source for copying conditions. There is NO
162 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
164 Written by Brendan O'Dea <bod@debian.org>
167 my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
168 `%s' generates a man page out of `--help' and `--version' output.
170 Usage: %s [OPTION]... EXECUTABLE
172 -n, --name=STRING description for the NAME paragraph
173 -s, --section=SECTION section number for manual page (1, 6, 8)
174 -m, --manual=TEXT name of manual (User Commands, ...)
175 -S, --source=TEXT source of program (FSF, Debian, ...)
176 -L, --locale=STRING select locale (default "C")
177 -i, --include=FILE include material from `FILE'
178 -I, --opt-include=FILE include material from `FILE' if it exists
179 -o, --output=FILE send output to `FILE'
180 -p, --info-page=TEXT name of Texinfo manual
181 -N, --no-info suppress pointer to Texinfo manual
182 -l, --libtool exclude the `lt-' from the program name
183 --help print this help, then exit
184 --version print version number, then exit
186 EXECUTABLE should accept `--help' and `--version' options and produce output on
187 stdout although alternatives may be specified using:
189 -h, --help-option=STRING help option string
190 -v, --version-option=STRING version option string
191 --version-string=STRING version string
192 --no-discard-stderr include stderr when parsing option output
194 Report bugs to <bug-help2man@gnu.org>.
200 my $help_option = '--help';
201 my $version_option = '--version';
202 my $discard_stderr = 1;
203 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
207 'n|name=s' => \$opt_name,
208 's|section=s' => \$section,
209 'm|manual=s' => \$manual,
210 'S|source=s' => \$source,
211 'L|locale=s' => sub { configure_locale pop },
212 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
213 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
214 'o|output=s' => \$opt_output,
215 'p|info-page=s' => \$opt_info,
216 'N|no-info' => \$opt_no_info,
217 'l|libtool' => \$opt_libtool,
218 'help' => sub { print $help_info; exit },
219 'version' => sub { print $version_info; exit },
220 'h|help-option=s' => \$help_option,
221 'v|version-option=s' => \$version_option,
222 'version-string=s' => \$version_text,
223 'discard-stderr!' => \$discard_stderr,
227 Getopt::Long::config('bundling');
228 die $help_info unless GetOptions %opt_def and @ARGV == 1;
232 print OUT <<'!NO!SUBS!' if $opts{'with-gettext'};
233 configure_locale unless $encoding;
237 # No substitutions for the remainder of the script:
238 print OUT <<'!NO!SUBS!';
241 my @include = (); # retain order given in include file
243 # Process include file (if given). Format is:
256 my ($inc, $required) = @{shift @opt_include};
258 next unless -f $inc or $required;
259 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
260 unless open INC, $inc;
263 my $hash = \%include;
267 # Convert input to internal Perl format, so that multibyte
268 # sequences are treated as single characters.
272 if (/^\[([^]]+)\]\s*$/)
278 push @include, $key unless $include{$key};
283 if (m!^/(.*)/([ims]*)\s*$!)
285 my $pat = $2 ? "(?$2)$1" : $1;
288 eval { $key = qr($pat) };
291 $@ =~ s/ at .*? line \d.*//;
299 # Check for options before the first section--anything else is
300 # silently ignored, allowing the first for comments and
314 $hash->{$key} ||= '';
320 kark N_("%s: no valid information found in `%s'"), $this_program, $inc
324 # Compress trailing blank lines.
325 for my $hash (\(%include, %append))
327 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
330 sub get_option_value;
332 # Grab help and version info from executable.
333 my $help_text = get_option_value $ARGV[0], $help_option;
334 $version_text ||= get_option_value $ARGV[0], $version_option;
336 # Translators: the following message is a strftime(3) format string, which in
337 # the English version expands to the month as a word and the full year. It
338 # is used on the footer of the generated manual pages. If in doubt, you may
339 # just use %x as the value (which should be the full locale-specific date).
340 my $date = enc strftime _("%B %Y"), localtime;
341 (my $program = $ARGV[0]) =~ s!.*/!!;
342 my $package = $program;
347 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
348 $this_program, $opt_output, $! if -e $opt_output;
350 open STDOUT, ">$opt_output"
351 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
354 # The first line of the --version information is assumed to be in one
355 # of the following formats:
358 # <program> <version>
359 # {GNU,Free} <program> <version>
360 # <program> ({GNU,Free} <package>) <version>
361 # <program> - {GNU,Free} <package> <version>
363 # and separated from any copyright/author details by a blank line.
365 ($_, $version_text) = ((split /\n+/, $version_text, 2), '');
367 if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
368 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
374 elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
377 $package = $1 ? "$1$2" : $2;
387 # No info for `info' itself.
388 $opt_no_info = 1 if $program eq 'info';
390 # Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
391 # upper case are manual page section headings. The man(1) manual page in your
392 # language, if available should provide the conventional translations.
393 for ($include{_('NAME')})
395 if ($opt_name) # --name overrides --include contents.
397 $_ = "$program \\- $opt_name\n";
399 elsif ($_) # Use first name given as $program
401 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
403 else # Set a default (useless) NAME paragraph.
405 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
410 # Man pages traditionally have the page title in caps.
411 my $PROGRAM = uc $program;
413 # Set default page head/footers
414 $source ||= "$program $version";
419 if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') }
420 elsif (/^6/) { $manual = enc _('Games') }
421 else { $manual = enc _('User Commands') }
425 # Extract usage clause(s) [if any] for SYNOPSIS.
426 # Translators: "Usage" and "or" here are patterns (regular expressions) which
427 # are used to match the usage synopsis in program output. An example from cp
428 # (GNU coreutils) which contains both strings:
429 # Usage: cp [OPTION]... [-T] SOURCE DEST
430 # or: cp [OPTION]... SOURCE... DIRECTORY
431 # or: cp [OPTION]... -t DIRECTORY SOURCE...
432 my $PAT_USAGE = _('Usage');
433 my $PAT_USAGE_CONT = _('or');
434 if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
441 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
447 $synopsis .= ".br\n" if $synopsis;
449 s/^lt-// if $opt_libtool;
451 $synopsis .= ".B $1\n";
453 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
454 s/^/\\fI/ unless s/^\\fR//;
465 $include{_('SYNOPSIS')} ||= $synopsis;
468 # Process text, initial section is DESCRIPTION.
469 my $sect = _('DESCRIPTION');
470 $_ = "$help_text\n\n$version_text";
472 # Normalise paragraph breaks.
477 # Join hyphenated lines.
478 s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
480 # Temporarily exchange leading dots, apostrophes and backslashes for
486 # Translators: patterns are used to match common program output. In the source
487 # these strings are all of the form of "my $PAT_something = _('...');" and are
488 # regular expressions. If there is more than one commonly used string, you
489 # may separate alternatives with "|". Spaces in these expressions are written
490 # as " +" to indicate that more than one space may be matched. The string
491 # "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
492 # optional word, so that either "Report bugs" or "Report _program_ bugs" will
494 my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to');
495 my $PAT_AUTHOR = _('Written +by');
496 my $PAT_OPTIONS = _('Options');
497 my $PAT_ENVIRONMENT = _('Environment');
498 my $PAT_FILES = _('Files');
499 my $PAT_EXAMPLES = _('Examples');
500 my $PAT_FREE_SOFTWARE = _('This +is +free +software');
502 # Start a new paragraph (if required) for these.
503 s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og;
505 # Convert iso-8859-1 copyright symbol or (c) to nroff
507 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
513 # Convert some standard paragraph names.
514 if (s/^($PAT_OPTIONS): *\n//o)
516 $sect = _('OPTIONS');
519 if (s/^($PAT_ENVIRONMENT): *\n//o)
521 $sect = _('ENVIRONMENT');
524 if (s/^($PAT_FILES): *\n//o)
529 elsif (s/^($PAT_EXAMPLES): *\n//o)
531 $sect = _('EXAMPLES');
538 $sect = _('COPYRIGHT');
541 # Bug reporting section.
542 elsif (/^($PAT_BUGS) /o)
544 $sect = _('REPORTING BUGS');
548 elsif (/^($PAT_AUTHOR)/o)
553 # Examples, indicated by an indented leading $, % or > are
554 # rendered in a constant width font.
555 if (/^( +)([\$\%>] )\S/)
560 $include{$sect} ||= '';
561 while (s/^$indent\Q$prefix\E(\S.*)\n*//)
563 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
571 $include{$sect} ||= '';
573 # Sub-sections have a trailing colon and the second line indented.
574 if (s/^(\S.*:) *\n / /)
576 $matched .= $& if %append;
577 $include{$sect} .= qq(.SS "$1"\n);
583 # Option with description.
584 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
586 $matched .= $& if %append;
587 $indent = length ($4 || "$1$3");
588 $content = ".TP\n\x84$2\n\x84$5\n";
591 # Indent may be different on second line.
592 $indent = length $& if /^ {20,}/;
596 # Option without description.
597 elsif (s/^ {1,10}([+-]\S.*)\n//)
599 $matched .= $& if %append;
600 $content = ".HP\n\x84$1\n";
601 $indent = 80; # not continued
604 # Indented paragraph with tag.
605 elsif (s/^( +(\S.*?) +)(\S.*)\n//)
607 $matched .= $& if %append;
609 $content = ".TP\n\x84$2\n\x84$3\n";
612 # Indented paragraph.
613 elsif (s/^( +)(\S.*)\n//)
615 $matched .= $& if %append;
617 $content = ".IP\n\x84$2\n";
620 # Left justified paragraph.
624 $matched .= $& if %append;
625 $content = ".PP\n" if $include{$sect};
629 # Append continuations.
630 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
632 $matched .= $& if %append;
633 $content .= "\x84$1\n";
636 # Move to next paragraph.
641 # Leading dot and apostrophe protection.
647 s/(^| |\()(-[][\w=-]+)/$1 . convert_option $2/mge;
649 # Escape remaining hyphens
652 if ($sect eq 'COPYRIGHT')
654 # Insert line breaks before additional copyright messages
655 # and the disclaimer.
656 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
658 elsif ($sect eq 'REPORTING BUGS')
660 # Handle multi-line bug reporting sections of the form:
662 # Report <program> bugs to <addr>
663 # GNU <package> home page: <url>
665 s/\n([[:upper:]])/\n.br\n$1/g;
669 # Check if matched paragraph contains /pat/.
672 for my $pat (keys %append)
674 if ($matched =~ $pat)
676 $content .= ".PP\n" unless $append{$pat} =~ /^\./;
677 $content .= $append{$pat};
682 $include{$sect} .= $content;
685 # Refer to the real documentation.
686 unless ($opt_no_info)
688 my $info_page = $opt_info || $program;
690 $sect = _('SEE ALSO');
691 $include{$sect} ||= '';
692 $include{$sect} .= ".PP\n" if $include{$sect};
693 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
694 The full documentation for
696 is maintained as a Texinfo manual. If the
700 programs are properly installed at your site, the command
704 should give you access to the complete manual.
710 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
711 .TH $PROGRAM "$section" "$date" "$source" "$manual"
715 my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
716 _('ENVIRONMENT'), _('FILES'), _('EXAMPLES'));
718 my @post = (_('AUTHOR'), _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
719 my $filter = join '|', @pre, @post;
722 for my $sect (@pre, (grep ! /^($filter)$/o, @include), @post)
726 my $quote = $sect =~ /\W/ ? '"' : '';
727 print enc ".SH $quote$sect$quote\n";
729 for ($include{$sect})
731 # Replace leading dot, apostrophe, backslash and hyphen
738 # Convert some latin1 chars to troff equivalents
739 s/\xa0/\\ /g; # non-breaking space
746 close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
747 $opt_output || 'stdout', $!;
751 # Call program with given option and return results.
754 my ($prog, $opt) = @_;
755 my $stderr = $discard_stderr ? '/dev/null' : '&1';
757 map { s/ +$//; expand $_ }
759 `$prog $opt 2>$stderr`;
763 my $err = N_("%s: can't get `%s' info from %s%s");
764 my $extra = $discard_stderr
765 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr")
768 kark $err, $this_program, $opt, $prog, $extra;
774 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
775 # embolden. Option arguments get italicised.
778 local $_ = '\fB' . shift;
781 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
792 # Rename output and fix permissions
793 unless ($opts{stdout})
796 rename $tmp, $target or die "$0: can't rename $tmp to $target ($!)\n";
797 chmod 0555, $target or warn "$0: can't change mode of $target ($!)\n";