3 # Generate a short man page from --help and --version output.
4 # Copyright (C) 1997-2012 Free Software Foundation, Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, see <http://www.gnu.org/licenses/>.
19 # Written by Brendan O'Dea <bod@debian.org>
20 # Available from ftp://ftp.gnu.org/gnu/help2man/
25 use Text::Tabs qw(expand);
26 use POSIX qw(strftime setlocale LC_ALL);
28 my $this_program = 'help2man';
29 my $this_version = '1.40.8';
35 die "$this_program: no locale support (Locale::gettext required)\n"
36 unless $locale eq 'C';
41 sub enc_user { $_[0] }
42 sub kark { die +(sprintf shift, @_), "\n" }
45 my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
48 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010,
49 2011, 2012 Free Software Foundation, Inc.
50 This is free software; see the source for copying conditions. There is NO
51 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
53 Written by Brendan O'Dea <bod@debian.org>
56 my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
57 `%s' generates a man page out of `--help' and `--version' output.
59 Usage: %s [OPTION]... EXECUTABLE
61 -n, --name=STRING description for the NAME paragraph
62 -s, --section=SECTION section number for manual page (1, 6, 8)
63 -m, --manual=TEXT name of manual (User Commands, ...)
64 -S, --source=TEXT source of program (FSF, Debian, ...)
65 -L, --locale=STRING select locale (default "C")
66 -i, --include=FILE include material from `FILE'
67 -I, --opt-include=FILE include material from `FILE' if it exists
68 -o, --output=FILE send output to `FILE'
69 -p, --info-page=TEXT name of Texinfo manual
70 -N, --no-info suppress pointer to Texinfo manual
71 -l, --libtool exclude the `lt-' from the program name
72 --help print this help, then exit
73 --version print version number, then exit
75 EXECUTABLE should accept `--help' and `--version' options and produce output on
76 stdout although alternatives may be specified using:
78 -h, --help-option=STRING help option string
79 -v, --version-option=STRING version option string
80 --version-string=STRING version string
81 --no-discard-stderr include stderr when parsing option output
83 Report bugs to <bug-help2man@gnu.org>.
89 my $help_option = '--help';
90 my $version_option = '--version';
91 my $discard_stderr = 1;
92 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
96 'n|name=s' => \$opt_name,
97 's|section=s' => \$section,
98 'm|manual=s' => \$manual,
99 'S|source=s' => \$source,
100 'L|locale=s' => sub { configure_locale pop },
101 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
102 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
103 'o|output=s' => \$opt_output,
104 'p|info-page=s' => \$opt_info,
105 'N|no-info' => \$opt_no_info,
106 'l|libtool' => \$opt_libtool,
107 'help' => sub { print $help_info; exit },
108 'version' => sub { print $version_info; exit },
109 'h|help-option=s' => \$help_option,
110 'v|version-option=s' => \$version_option,
111 'version-string=s' => \$version_text,
112 'discard-stderr!' => \$discard_stderr,
116 Getopt::Long::config('bundling');
117 die $help_info unless GetOptions %opt_def and @ARGV == 1;
121 my @include = (); # retain order given in include file
123 # Process include file (if given). Format is:
136 my ($inc, $required) = @{shift @opt_include};
138 next unless -f $inc or $required;
139 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
140 unless open INC, $inc;
143 my $hash = \%include;
147 # Convert input to internal Perl format, so that multibyte
148 # sequences are treated as single characters.
152 if (/^\[([^]]+)\]\s*$/)
158 push @include, $key unless $include{$key};
163 if (m!^/(.*)/([ims]*)\s*$!)
165 my $pat = $2 ? "(?$2)$1" : $1;
168 eval { $key = qr($pat) };
171 $@ =~ s/ at .*? line \d.*//;
179 # Check for options before the first section--anything else is
180 # silently ignored, allowing the first for comments and
194 $hash->{$key} ||= '';
200 kark N_("%s: no valid information found in `%s'"), $this_program, $inc
204 # Compress trailing blank lines.
205 for my $hash (\(%include, %append))
207 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
210 sub get_option_value;
212 # Grab help and version info from executable.
213 my $help_text = get_option_value $ARGV[0], $help_option;
214 $version_text ||= get_option_value $ARGV[0], $version_option;
216 # Translators: the following message is a strftime(3) format string, which in
217 # the English version expands to the month as a word and the full year. It
218 # is used on the footer of the generated manual pages. If in doubt, you may
219 # just use %x as the value (which should be the full locale-specific date).
220 my $date = enc strftime _("%B %Y"), localtime;
221 (my $program = $ARGV[0]) =~ s!.*/!!;
222 my $package = $program;
227 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
228 $this_program, $opt_output, $! if -e $opt_output;
230 open STDOUT, ">$opt_output"
231 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
234 # The first line of the --version information is assumed to be in one
235 # of the following formats:
238 # <program> <version>
239 # {GNU,Free} <program> <version>
240 # <program> ({GNU,Free} <package>) <version>
241 # <program> - {GNU,Free} <package> <version>
243 # and separated from any copyright/author details by a blank line.
245 ($_, $version_text) = ((split /\n+/, $version_text, 2), '');
247 if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
248 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
254 elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
257 $package = $1 ? "$1$2" : $2;
267 # No info for `info' itself.
268 $opt_no_info = 1 if $program eq 'info';
270 # Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
271 # upper case are manual page section headings. The man(1) manual page in your
272 # language, if available should provide the conventional translations.
273 for ($include{_('NAME')})
275 if ($opt_name) # --name overrides --include contents.
277 $_ = "$program \\- $opt_name\n";
279 elsif ($_) # Use first name given as $program
281 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
283 else # Set a default (useless) NAME paragraph.
285 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
290 # Man pages traditionally have the page title in caps.
291 my $PROGRAM = uc $program;
293 # Set default page head/footers
294 $source ||= "$program $version";
299 if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') }
300 elsif (/^6/) { $manual = enc _('Games') }
301 else { $manual = enc _('User Commands') }
305 # Extract usage clause(s) [if any] for SYNOPSIS.
306 # Translators: "Usage" and "or" here are patterns (regular expressions) which
307 # are used to match the usage synopsis in program output. An example from cp
308 # (GNU coreutils) which contains both strings:
309 # Usage: cp [OPTION]... [-T] SOURCE DEST
310 # or: cp [OPTION]... SOURCE... DIRECTORY
311 # or: cp [OPTION]... -t DIRECTORY SOURCE...
312 my $PAT_USAGE = _('Usage');
313 my $PAT_USAGE_CONT = _('or');
314 if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
321 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
327 $synopsis .= ".br\n" if $synopsis;
329 s/^lt-// if $opt_libtool;
331 $synopsis .= ".B $1\n";
333 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
334 s/^/\\fI/ unless s/^\\fR//;
345 $include{_('SYNOPSIS')} ||= $synopsis;
348 # Process text, initial section is DESCRIPTION.
349 my $sect = _('DESCRIPTION');
350 $_ = "$help_text\n\n$version_text";
352 # Normalise paragraph breaks.
357 # Join hyphenated lines.
358 s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
360 # Temporarily exchange leading dots, apostrophes and backslashes for
366 # Translators: patterns are used to match common program output. In the source
367 # these strings are all of the form of "my $PAT_something = _('...');" and are
368 # regular expressions. If there is more than one commonly used string, you
369 # may separate alternatives with "|". Spaces in these expressions are written
370 # as " +" to indicate that more than one space may be matched. The string
371 # "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
372 # optional word, so that either "Report bugs" or "Report _program_ bugs" will
374 my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to');
375 my $PAT_AUTHOR = _('Written +by');
376 my $PAT_OPTIONS = _('Options');
377 my $PAT_ENVIRONMENT = _('Environment');
378 my $PAT_FILES = _('Files');
379 my $PAT_EXAMPLES = _('Examples');
380 my $PAT_FREE_SOFTWARE = _('This +is +free +software');
382 # Start a new paragraph (if required) for these.
383 s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og;
385 # Convert iso-8859-1 copyright symbol or (c) to nroff
387 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
393 # Convert some standard paragraph names.
394 if (s/^($PAT_OPTIONS): *\n//o)
396 $sect = _('OPTIONS');
399 if (s/^($PAT_ENVIRONMENT): *\n//o)
401 $sect = _('ENVIRONMENT');
404 if (s/^($PAT_FILES): *\n//o)
409 elsif (s/^($PAT_EXAMPLES): *\n//o)
411 $sect = _('EXAMPLES');
418 $sect = _('COPYRIGHT');
421 # Bug reporting section.
422 elsif (/^($PAT_BUGS) /o)
424 $sect = _('REPORTING BUGS');
428 elsif (/^($PAT_AUTHOR)/o)
433 # Examples, indicated by an indented leading $, % or > are
434 # rendered in a constant width font.
435 if (/^( +)([\$\%>] )\S/)
440 $include{$sect} ||= '';
441 while (s/^$indent\Q$prefix\E(\S.*)\n*//)
443 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
451 $include{$sect} ||= '';
453 # Sub-sections have a trailing colon and the second line indented.
454 if (s/^(\S.*:) *\n / /)
456 $matched .= $& if %append;
457 $include{$sect} .= qq(.SS "$1"\n);
463 # Option with description.
464 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
466 $matched .= $& if %append;
467 $indent = length ($4 || "$1$3");
468 $content = ".TP\n\x84$2\n\x84$5\n";
471 # Indent may be different on second line.
472 $indent = length $& if /^ {20,}/;
476 # Option without description.
477 elsif (s/^ {1,10}([+-]\S.*)\n//)
479 $matched .= $& if %append;
480 $content = ".HP\n\x84$1\n";
481 $indent = 80; # not continued
484 # Indented paragraph with tag.
485 elsif (s/^( +(\S.*?) +)(\S.*)\n//)
487 $matched .= $& if %append;
489 $content = ".TP\n\x84$2\n\x84$3\n";
492 # Indented paragraph.
493 elsif (s/^( +)(\S.*)\n//)
495 $matched .= $& if %append;
497 $content = ".IP\n\x84$2\n";
500 # Left justified paragraph.
504 $matched .= $& if %append;
505 $content = ".PP\n" if $include{$sect};
509 # Append continuations.
510 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
512 $matched .= $& if %append;
513 $content .= "\x84$1\n";
516 # Move to next paragraph.
521 # Leading dot and apostrophe protection.
527 s/(^| |\()(-[][\w=-]+)/$1 . convert_option $2/mge;
529 # Escape remaining hyphens
532 if ($sect eq 'COPYRIGHT')
534 # Insert line breaks before additional copyright messages
535 # and the disclaimer.
536 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
538 elsif ($sect eq 'REPORTING BUGS')
540 # Handle multi-line bug reporting sections of the form:
542 # Report <program> bugs to <addr>
543 # GNU <package> home page: <url>
545 s/\n([[:upper:]])/\n.br\n$1/g;
549 # Check if matched paragraph contains /pat/.
552 for my $pat (keys %append)
554 if ($matched =~ $pat)
556 $content .= ".PP\n" unless $append{$pat} =~ /^\./;
557 $content .= $append{$pat};
562 $include{$sect} .= $content;
565 # Refer to the real documentation.
566 unless ($opt_no_info)
568 my $info_page = $opt_info || $program;
570 $sect = _('SEE ALSO');
571 $include{$sect} ||= '';
572 $include{$sect} .= ".PP\n" if $include{$sect};
573 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
574 The full documentation for
576 is maintained as a Texinfo manual. If the
580 programs are properly installed at your site, the command
584 should give you access to the complete manual.
590 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
591 .TH $PROGRAM "$section" "$date" "$source" "$manual"
595 my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
596 _('ENVIRONMENT'), _('FILES'), _('EXAMPLES'));
598 my @post = (_('AUTHOR'), _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
599 my $filter = join '|', @pre, @post;
602 for my $sect (@pre, (grep ! /^($filter)$/o, @include), @post)
606 my $quote = $sect =~ /\W/ ? '"' : '';
607 print enc ".SH $quote$sect$quote\n";
609 for ($include{$sect})
611 # Replace leading dot, apostrophe, backslash and hyphen
618 # Convert some latin1 chars to troff equivalents
619 s/\xa0/\\ /g; # non-breaking space
626 close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
627 $opt_output || 'stdout', $!;
631 # Call program with given option and return results.
634 my ($prog, $opt) = @_;
635 my $stderr = $discard_stderr ? '/dev/null' : '&1';
637 map { s/ +$//; expand $_ }
639 `$prog $opt 2>$stderr`;
643 my $err = N_("%s: can't get `%s' info from %s%s");
644 my $extra = $discard_stderr
645 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr")
648 kark $err, $this_program, $opt, $prog, $extra;
654 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
655 # embolden. Option arguments get italicised.
658 local $_ = '\fB' . shift;
661 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)