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.47.5');
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, 2013, 2014, 2015, 2016, 2017 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::ParseWords qw(shellwords);
87 use Text::Tabs qw(expand);
88 use POSIX qw(strftime setlocale LC_ALL);
91 print OUT <<'!NO!SUBS!' if $opts{'with-gettext'};
92 use Locale::gettext qw(gettext);
93 use Encode qw(decode encode);
94 use I18N::Langinfo qw(langinfo CODESET);
97 # Interpolate program name and version:
98 print OUT <<"!GROK!THIS!";
100 my \$this_program = '$program';
101 my \$this_version = '$version';
104 # Conditionally include gettext support:
105 print OUT $opts{'with-gettext'} ? <<'!WITH!GETTEXT!' : <<'!NO!GETTEXT!';
109 my $gettext = Locale::gettext->domain($this_program);
110 sub _ { $gettext->get($_[0]) }
112 my ($user_locale) = grep defined && length,
113 (map $ENV{$_}, qw(LANGUAGE LC_ALL LC_MESSAGES LANG)), 'C';
115 my $user_encoding = langinfo CODESET;
117 # Set localisation of date and executable's output.
120 delete @ENV{qw(LANGUAGE LC_MESSAGES LANG)};
121 setlocale LC_ALL, $ENV{LC_ALL} = shift || 'C';
122 $encoding = langinfo CODESET;
125 sub dec { $encoding ? decode $encoding, $_[0] : $_[0] }
126 sub enc { $encoding ? encode $encoding, $_[0] : $_[0] }
127 sub enc_user { encode $user_encoding, $_[0] }
128 sub kark # die with message formatted in the invoking user's locale
130 setlocale LC_ALL, $user_locale;
131 my $fmt = $gettext->get(shift);
132 my $errmsg = enc_user sprintf $fmt, @_;
143 die "$this_program: no locale support (Locale::gettext required)\n"
144 unless $locale eq 'C';
149 sub enc_user { $_[0] }
150 sub kark { die +(sprintf shift, @_), "\n" }
153 # No substitutions for this chunk:
154 print OUT <<'!NO!SUBS!';
157 sub program_basename;
158 sub get_option_value;
160 sub fix_italic_spacing;
162 my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
165 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010,
166 2011, 2012, 2013, 2014, 2015, 2016, 2017 Free Software Foundation, Inc.
167 This is free software; see the source for copying conditions. There is NO
168 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
170 Written by Brendan O'Dea <bod@debian.org>
173 my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
174 `%s' generates a man page out of `--help' and `--version' output.
176 Usage: %s [OPTION]... EXECUTABLE
178 -n, --name=STRING description for the NAME paragraph
179 -s, --section=SECTION section number for manual page (1, 6, 8)
180 -m, --manual=TEXT name of manual (User Commands, ...)
181 -S, --source=TEXT source of program (FSF, Debian, ...)
182 -L, --locale=STRING select locale (default "C")
183 -i, --include=FILE include material from `FILE'
184 -I, --opt-include=FILE include material from `FILE' if it exists
185 -o, --output=FILE send output to `FILE'
186 -p, --info-page=TEXT name of Texinfo manual
187 -N, --no-info suppress pointer to Texinfo manual
188 -l, --libtool exclude the `lt-' from the program name
189 --help print this help, then exit
190 --version print version number, then exit
192 EXECUTABLE should accept `--help' and `--version' options and produce output on
193 stdout although alternatives may be specified using:
195 -h, --help-option=STRING help option string
196 -v, --version-option=STRING version option string
197 --version-string=STRING version string
198 --no-discard-stderr include stderr when parsing option output
200 Report bugs to <bug-help2man@gnu.org>.
206 my $help_option = '--help';
207 my $version_option = '--version';
208 my $discard_stderr = 1;
209 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
213 'n|name=s' => \$opt_name,
214 's|section=s' => \$section,
215 'm|manual=s' => \$manual,
216 'S|source=s' => \$source,
217 'L|locale=s' => sub { configure_locale pop },
218 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
219 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
220 'o|output=s' => \$opt_output,
221 'p|info-page=s' => \$opt_info,
222 'N|no-info' => \$opt_no_info,
223 'l|libtool' => \$opt_libtool,
224 'help' => sub { print $help_info; exit },
225 'version' => sub { print $version_info; exit },
226 'h|help-option=s' => \$help_option,
227 'v|version-option=s' => \$version_option,
228 'version-string=s' => \$version_text,
229 'discard-stderr!' => \$discard_stderr,
233 Getopt::Long::config('bundling');
234 die $help_info unless GetOptions %opt_def and @ARGV == 1;
238 print OUT <<'!NO!SUBS!' if $opts{'with-gettext'};
239 configure_locale unless $encoding;
243 # No substitutions for the remainder of the script:
244 print OUT <<'!NO!SUBS!';
248 my %append_match = ();
249 my @sections = (); # retain order of include file or in-line *section*s
251 # Process include file (if given). Format is:
253 # Optional initial text, ignored. May include lines starting with `-'
254 # which are processed as options.
257 # Verbatim text to be included in the named section. By default at
258 # the start, but in the case of `name' and `synopsis' the content
259 # will replace the autogenerated contents.
262 # Verbatim text to be inserted at the start of the named section.
265 # Verbatim text to replace the named section.
268 # Verbatim text to be appended to the end of the named section.
271 # Verbatim text for inclusion below a paragraph matching `pattern'.
276 my ($inc, $required) = @{shift @opt_include};
278 next unless -f $inc or $required;
279 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
280 unless open INC, $inc;
287 # Convert input to internal Perl format, so that multibyte
288 # sequences are treated as single characters.
292 if (/^\[([^]]+)\]\s*$/)
298 # Handle explicit [<section], [=section] and [>section]
299 if ($key =~ s/^([<>=])\s*//)
301 if ($1 eq '>') { $hash = \%append; }
302 elsif ($1 eq '=') { $hash = \%replace; }
304 # NAME/SYNOPSIS replace by default
305 elsif ($key eq _('NAME') or $key eq _('SYNOPSIS'))
314 push @sections, $key;
319 if (m!^/(.*)/([ims]*)\s*$!)
321 my $pat = $2 ? "(?$2)$1" : $1;
324 eval { $key = qr($pat) };
327 $@ =~ s/ at .*? line \d.*//;
331 $hash = \%append_match;
335 # Check for options before the first section--anything else is
336 # silently ignored, allowing the first for comments and
343 local @ARGV = shellwords $_;
355 kark N_("%s: no valid information found in `%s'"), $this_program, $inc
359 # Compress trailing blank lines.
360 for my $hash (\(%include, %replace, %append, %append_match))
362 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
365 # Grab help and version info from executable.
366 my $help_text = get_option_value $ARGV[0], $help_option;
367 $version_text ||= get_option_value $ARGV[0], $version_option;
369 # By default the generated manual pages will include the current date. This may
370 # however be overriden by setting the environment variable $SOURCE_DATE_EPOCH to
371 # an integer value of the seconds since the UNIX epoch. This is primarily
372 # intended to support reproducible builds (wiki.debian.org/ReproducibleBuilds)
373 # and will additionally ensure that the output date string is UTC.
374 my $epoch_secs = time;
375 if (exists $ENV{SOURCE_DATE_EPOCH} and $ENV{SOURCE_DATE_EPOCH} =~ /^(\d+)$/)
381 # Translators: the following message is a strftime(3) format string, which in
382 # the English version expands to the month as a word and the full year. It
383 # is used on the footer of the generated manual pages. If in doubt, you may
384 # just use %x as the value (which should be the full locale-specific date).
385 my $date = enc strftime _("%B %Y"), localtime $epoch_secs;
386 my $program = program_basename $ARGV[0];
387 my $package = $program;
392 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
393 $this_program, $opt_output, $! if -e $opt_output;
395 open STDOUT, ">$opt_output"
396 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
399 # The first line of the --version information is assumed to be in one
400 # of the following formats:
403 # <program> <version>
404 # {GNU,Free} <program> <version>
405 # <program> ({GNU,Free} <package>) <version>
406 # <program> - {GNU,Free} <package> <version>
408 # and separated from any copyright/author details by a blank line.
410 ($_, $version_text) = ((split /\n+/, $version_text, 2), '');
412 if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
413 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
415 $program = program_basename $1;
419 elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
421 $program = program_basename $2;
422 $package = $1 ? "$1$program" : $program;
430 # No info for `info' itself.
431 $opt_no_info = 1 if $program eq 'info';
435 # --name overrides --include contents.
436 $replace{_('NAME')} = "$program \\- $opt_name\n";
439 # Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
440 # upper case are manual page section headings. The man(1) manual page in your
441 # language, if available should provide the conventional translations.
442 for ($replace{_('NAME')} || ($include{_('NAME')} ||= ''))
444 if ($_) # Use first name given as $program
446 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
448 else # Set a default (useless) NAME paragraph.
450 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
455 # Man pages traditionally have the page title in caps.
456 my $PROGRAM = uc $program;
458 # Set default page head/footers
459 $source ||= "$program $version";
464 if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') }
465 elsif (/^6/) { $manual = enc _('Games') }
466 else { $manual = enc _('User Commands') }
470 # Extract usage clause(s) [if any] for SYNOPSIS.
471 # Translators: "Usage" and "or" here are patterns (regular expressions) which
472 # are used to match the usage synopsis in program output. An example from cp
473 # (GNU coreutils) which contains both strings:
474 # Usage: cp [OPTION]... [-T] SOURCE DEST
475 # or: cp [OPTION]... SOURCE... DIRECTORY
476 # or: cp [OPTION]... -t DIRECTORY SOURCE...
477 my $PAT_USAGE = _('Usage');
478 my $PAT_USAGE_CONT = _('or');
479 if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
486 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
492 $synopsis .= ".br\n" if $synopsis;
494 s/^lt-// if $opt_libtool;
496 $synopsis .= ".B $1\n";
498 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
499 s/^/\\fI/ unless s/^\\fR//;
507 $_ = fix_italic_spacing $_;
511 $include{_('SYNOPSIS')} .= $synopsis;
514 # Process text, initial section is DESCRIPTION.
515 my $sect = _('DESCRIPTION');
516 $_ = "$help_text\n\n$version_text";
518 # Normalise paragraph breaks.
523 # Join hyphenated lines.
524 s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
526 # Temporarily exchange leading dots, apostrophes and backslashes for
532 # Translators: patterns are used to match common program output. In the source
533 # these strings are all of the form of "my $PAT_something = _('...');" and are
534 # regular expressions. If there is more than one commonly used string, you
535 # may separate alternatives with "|". Spaces in these expressions are written
536 # as " +" to indicate that more than one space may be matched. The string
537 # "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
538 # optional word, so that either "Report bugs" or "Report _program_ bugs" will
540 my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to');
541 my $PAT_AUTHOR = _('Written +by');
542 my $PAT_OPTIONS = _('Options');
543 my $PAT_ENVIRONMENT = _('Environment');
544 my $PAT_FILES = _('Files');
545 my $PAT_EXAMPLES = _('Examples');
546 my $PAT_FREE_SOFTWARE = _('This +is +free +software');
548 # Start a new paragraph (if required) for these.
549 s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og;
551 # Convert iso-8859-1 copyright symbol or (c) to nroff
553 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
557 # Convert some standard paragraph names.
558 if (s/^($PAT_OPTIONS): *\n+//o)
560 $sect = _('OPTIONS');
563 if (s/^($PAT_ENVIRONMENT): *\n+//o)
565 $sect = _('ENVIRONMENT');
568 if (s/^($PAT_FILES): *\n+//o)
573 elsif (s/^($PAT_EXAMPLES): *\n+//o)
575 $sect = _('EXAMPLES');
579 # Custom section indicated by a line containing "*Section Name*".
580 if (s/^\*(\w(.*\w)?)\* *\n+//)
583 $sect =~ tr/*/ /; # also accept *Section*Name*
584 push @sections, $sect;
591 $sect = _('COPYRIGHT');
594 # Bug reporting section.
595 elsif (/^($PAT_BUGS) /o)
597 $sect = _('REPORTING BUGS');
601 elsif (/^($PAT_AUTHOR)/o)
606 # Examples, indicated by an indented leading $, % or > are
607 # rendered in a constant width font.
608 if (/^( +)([\$\%>] )\S/)
613 while (s/^$indent\Q$prefix\E(\S.*)\n*//)
615 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
624 # Sub-sections have a trailing colon and the second line indented.
625 if (s/^(\S.*:) *\n / /)
627 $matched .= $& if %append_match;
628 $include{$sect} .= qq(.SS "$1"\n);
634 # Option with description.
635 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
637 $matched .= $& if %append_match;
638 $indent = length ($4 || "$1$3");
639 $content = ".TP\n\x84$2\n\x84$5\n";
642 # Indent may be different on second line.
643 $indent = length $& if /^ {20,}/;
647 # Option without description.
648 elsif (s/^ {1,10}([+-]\S.*)\n//)
650 $matched .= $& if %append_match;
651 $content = ".HP\n\x84$1\n";
652 $indent = 80; # not continued
655 # Indented paragraph with tag.
656 elsif (s/^( +(\S.*?))(?:( +)|\n( {20,}))(\S.*)\n//)
658 $matched .= $& if %append_match;
659 $indent = length ($4 || "$1$3");
660 $content = ".TP\n\x84$2\n\x84$5\n";
663 # Indented paragraph.
664 elsif (s/^( +)(\S.*)\n//)
666 $matched .= $& if %append_match;
668 $content = ".IP\n\x84$2\n";
671 # Left justified paragraph.
675 $matched .= $& if %append_match;
676 $content = ".PP\n" if $include{$sect};
680 # Append continuations.
681 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
683 $matched .= $& if %append_match;
684 $content .= "\x84$1\n";
687 # Move to next paragraph.
692 # Leading dot and apostrophe protection.
697 # Examples should be verbatim.
698 unless ($sect eq _('EXAMPLES'))
701 s/(^|[ (])(-[][\w=-]+)/$1 . convert_option $2/mge;
703 # Italicise filenames: /a/b, $VAR/c/d, ~/e/f
705 (^|[ (]) # space/punctuation before
707 (?:\$\w+|~)? # leading variable, or tilde
708 (?:/\w(?:[\w.-]*\w)?)+ # path components
710 ($|[ ,;.)]) # space/punctuation after
713 $_ = fix_italic_spacing $_;
716 # Escape remaining hyphens.
719 if ($sect eq _('COPYRIGHT'))
721 # Insert line breaks before additional copyright messages
722 # and the disclaimer.
723 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
725 elsif ($sect eq _('REPORTING BUGS'))
727 # Handle multi-line bug reporting sections of the form:
729 # Report <program> bugs to <addr>
730 # GNU <package> home page: <url>
732 s/\n([[:upper:]])/\n.br\n$1/g;
736 # Check if matched paragraph contains /pat/.
739 for my $pat (keys %append_match)
741 if ($matched =~ $pat)
743 $content .= ".PP\n" unless $append_match{$pat} =~ /^\./;
744 $content .= $append_match{$pat};
749 $include{$sect} .= $content;
752 # Refer to the real documentation.
753 unless ($opt_no_info)
755 my $info_page = $opt_info || $program;
757 $sect = _('SEE ALSO');
758 $include{$sect} .= ".PP\n" if $include{$sect};
759 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
760 The full documentation for
762 is maintained as a Texinfo manual. If the
766 programs are properly installed at your site, the command
770 should give you access to the complete manual.
774 # Append additional text.
775 while (my ($sect, $text) = each %append)
777 $include{$sect} .= $append{$sect};
781 while (my ($sect, $text) = each %replace)
783 $include{$sect} = $replace{$sect};
788 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
789 .TH $PROGRAM "$section" "$date" "$source" "$manual"
793 my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'));
794 my @post = (_('ENVIRONMENT'), _('FILES'), _('EXAMPLES'), _('AUTHOR'),
795 _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
796 my %filter = map { $_ => 1 } @pre, @post;
800 for my $sect (@pre, (grep !$filter{$_}, @sections), @post)
802 next if $done{$sect}++; # ignore duplicates
803 next unless $include{$sect};
806 my $quote = $sect =~ /\W/ ? '"' : '';
807 print enc ".SH $quote$sect$quote\n";
809 for ($include{$sect})
811 # Replace leading dot, apostrophe, backslash and hyphen
818 # Convert some latin1 chars to troff equivalents
819 s/\xa0/\\ /g; # non-breaking space
826 close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
827 $opt_output || 'stdout', $!;
831 # Get program basename, and strip libtool "lt-" prefix if required.
836 s/^lt-// if $opt_libtool;
840 # Call program with given option and return results.
843 my ($prog, $opt) = @_;
844 my $stderr = $discard_stderr ? '/dev/null' : '&1';
846 map { s/ +$//; expand $_ }
848 `$prog $opt 2>$stderr`;
852 my $err = N_("%s: can't get `%s' info from %s%s");
853 my $extra = $discard_stderr
854 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr")
857 kark $err, $this_program, $opt, $prog, $extra;
863 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
864 # embolden. Option arguments get italicised.
867 local $_ = '\fB' . shift;
870 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
880 # Insert spacing escape characters \, and \/ before and after italic text. See
881 # http://www.gnu.org/software/groff/manual/html_node/Ligatures-and-Kerning.html
882 sub fix_italic_spacing
885 s!\\fI(.*?)\\f([BRP])!\\fI\\,$1\\/\\f$2!g;
890 # Rename output and fix permissions
891 unless ($opts{stdout})
894 rename $tmp, $target or die "$0: can't rename $tmp to $target ($!)\n";
895 chmod 0555, $target or warn "$0: can't change mode of $target ($!)\n";