1#!/usr/bin/perl -w 2 3# Generate a short man page from --help and --version output. 4# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 5# 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Free Software Foundation, Inc. 6 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 3, or (at your option) 10# any later version. 11 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, see <http://www.gnu.org/licenses/>. 19 20# Written by Brendan O'Dea <bod@debian.org> 21# Available from ftp://ftp.gnu.org/gnu/help2man/ 22 23use 5.008; 24use strict; 25use Getopt::Long; 26use Text::ParseWords qw(shellwords); 27use Text::Tabs qw(expand); 28use POSIX qw(strftime setlocale LC_ALL); 29use Locale::gettext qw(gettext); 30use Encode qw(decode encode); 31use I18N::Langinfo qw(langinfo CODESET); 32 33my $this_program = 'help2man'; 34my $this_version = '1.47.6'; 35my $encoding; 36 37{ 38 my $gettext = Locale::gettext->domain($this_program); 39 sub _ { $gettext->get($_[0]) } 40 41 my ($user_locale) = grep defined && length, 42 (map $ENV{$_}, qw(LANGUAGE LC_ALL LC_MESSAGES LANG)), 'C'; 43 44 my $user_encoding = langinfo CODESET; 45 46 # Set localisation of date and executable's output. 47 sub configure_locale 48 { 49 delete @ENV{qw(LANGUAGE LC_MESSAGES LANG)}; 50 setlocale LC_ALL, $ENV{LC_ALL} = shift || 'C'; 51 $encoding = langinfo CODESET; 52 } 53 54 sub dec { $encoding ? decode $encoding, $_[0] : $_[0] } 55 sub enc { $encoding ? encode $encoding, $_[0] : $_[0] } 56 sub enc_user { encode $user_encoding, $_[0] } 57 sub kark # die with message formatted in the invoking user's locale 58 { 59 setlocale LC_ALL, $user_locale; 60 my $fmt = $gettext->get(shift); 61 my $errmsg = enc_user sprintf $fmt, @_; 62 die $errmsg, "\n"; 63 } 64} 65 66sub N_ { $_[0] } 67 68sub program_basename; 69sub get_option_value; 70sub convert_option; 71sub fix_italic_spacing; 72 73my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version; 74GNU %s %s 75 76Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, 772011, 2012, 2013, 2014, 2015, 2016, 2017 Free Software Foundation, Inc. 78This is free software; see the source for copying conditions. There is NO 79warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 80 81Written by Brendan O'Dea <bod@debian.org> 82EOT 83 84my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program; 85`%s' generates a man page out of `--help' and `--version' output. 86 87Usage: %s [OPTION]... EXECUTABLE 88 89 -n, --name=STRING description for the NAME paragraph 90 -s, --section=SECTION section number for manual page (1, 6, 8) 91 -m, --manual=TEXT name of manual (User Commands, ...) 92 -S, --source=TEXT source of program (FSF, Debian, ...) 93 -L, --locale=STRING select locale (default "C") 94 -i, --include=FILE include material from `FILE' 95 -I, --opt-include=FILE include material from `FILE' if it exists 96 -o, --output=FILE send output to `FILE' 97 -p, --info-page=TEXT name of Texinfo manual 98 -N, --no-info suppress pointer to Texinfo manual 99 -l, --libtool exclude the `lt-' from the program name 100 --help print this help, then exit 101 --version print version number, then exit 102 103EXECUTABLE should accept `--help' and `--version' options and produce output on 104stdout although alternatives may be specified using: 105 106 -h, --help-option=STRING help option string 107 -v, --version-option=STRING version option string 108 --version-string=STRING version string 109 --no-discard-stderr include stderr when parsing option output 110 111Report bugs to <bug-help2man@gnu.org>. 112EOT 113 114my $section = 1; 115my $manual = ''; 116my $source = ''; 117my $help_option = '--help'; 118my $version_option = '--version'; 119my $discard_stderr = 1; 120my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool, 121 $version_text); 122 123my %opt_def = ( 124 'n|name=s' => \$opt_name, 125 's|section=s' => \$section, 126 'm|manual=s' => \$manual, 127 'S|source=s' => \$source, 128 'L|locale=s' => sub { configure_locale pop }, 129 'i|include=s' => sub { push @opt_include, [ pop, 1 ] }, 130 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] }, 131 'o|output=s' => \$opt_output, 132 'p|info-page=s' => \$opt_info, 133 'N|no-info' => \$opt_no_info, 134 'l|libtool' => \$opt_libtool, 135 'help' => sub { print $help_info; exit }, 136 'version' => sub { print $version_info; exit }, 137 'h|help-option=s' => \$help_option, 138 'v|version-option=s' => \$version_option, 139 'version-string=s' => \$version_text, 140 'discard-stderr!' => \$discard_stderr, 141); 142 143# Parse options. 144Getopt::Long::config('bundling'); 145die $help_info unless GetOptions %opt_def and @ARGV == 1; 146 147configure_locale unless $encoding; 148 149my %include = (); 150my %replace = (); 151my %append = (); 152my %append_match = (); 153my @sections = (); # retain order of include file or in-line *section*s 154 155# Process include file (if given). Format is: 156# 157# Optional initial text, ignored. May include lines starting with `-' 158# which are processed as options. 159# 160# [section] 161# Verbatim text to be included in the named section. By default at 162# the start, but in the case of `name' and `synopsis' the content 163# will replace the autogenerated contents. 164# 165# [<section] 166# Verbatim text to be inserted at the start of the named section. 167# 168# [=section] 169# Verbatim text to replace the named section. 170# 171# [>section] 172# Verbatim text to be appended to the end of the named section. 173# 174# /pattern/ 175# Verbatim text for inclusion below a paragraph matching `pattern'. 176# 177 178while (@opt_include) 179{ 180 my ($inc, $required) = @{shift @opt_include}; 181 182 next unless -f $inc or $required; 183 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $! 184 unless open INC, $inc; 185 186 my $key; 187 my $hash; 188 189 while (<INC>) 190 { 191 # Convert input to internal Perl format, so that multibyte 192 # sequences are treated as single characters. 193 $_ = dec $_; 194 195 # [section] 196 if (/^\[([^]]+)\]\s*$/) 197 { 198 $key = uc $1; 199 $key =~ s/^\s+//; 200 $key =~ s/\s+$//; 201 $hash = \%include; 202 # Handle explicit [<section], [=section] and [>section] 203 if ($key =~ s/^([<>=])\s*//) 204 { 205 if ($1 eq '>') { $hash = \%append; } 206 elsif ($1 eq '=') { $hash = \%replace; } 207 } 208 # NAME/SYNOPSIS replace by default 209 elsif ($key eq _('NAME') or $key eq _('SYNOPSIS')) 210 { 211 $hash = \%replace; 212 } 213 else 214 { 215 $hash = \%include; 216 } 217 218 push @sections, $key; 219 next; 220 } 221 222 # /pattern/ 223 if (m!^/(.*)/([ims]*)\s*$!) 224 { 225 my $pat = $2 ? "(?$2)$1" : $1; 226 227 # Check pattern. 228 eval { $key = qr($pat) }; 229 if ($@) 230 { 231 $@ =~ s/ at .*? line \d.*//; 232 die "$inc:$.:$@"; 233 } 234 235 $hash = \%append_match; 236 next; 237 } 238 239 # Check for options before the first section--anything else is 240 # silently ignored, allowing the first for comments and 241 # revision info. 242 unless ($key) 243 { 244 # handle options 245 if (/^-/) 246 { 247 local @ARGV = shellwords $_; 248 GetOptions %opt_def; 249 } 250 251 next; 252 } 253 254 $hash->{$key} .= $_; 255 } 256 257 close INC; 258 259 kark N_("%s: no valid information found in `%s'"), $this_program, $inc 260 unless $key; 261} 262 263# Compress trailing blank lines. 264for my $hash (\(%include, %replace, %append, %append_match)) 265{ 266 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ } 267} 268 269# Grab help and version info from executable. 270my $help_text = get_option_value $ARGV[0], $help_option; 271$version_text ||= get_option_value $ARGV[0], $version_option; 272 273# By default the generated manual pages will include the current date. This may 274# however be overriden by setting the environment variable $SOURCE_DATE_EPOCH to 275# an integer value of the seconds since the UNIX epoch. This is primarily 276# intended to support reproducible builds (wiki.debian.org/ReproducibleBuilds) 277# and will additionally ensure that the output date string is UTC. 278my $epoch_secs = time; 279if (exists $ENV{SOURCE_DATE_EPOCH} and $ENV{SOURCE_DATE_EPOCH} =~ /^(\d+)$/) 280{ 281 $epoch_secs = $1; 282 $ENV{TZ} = 'UTC0'; 283} 284 285# Translators: the following message is a strftime(3) format string, which in 286# the English version expands to the month as a word and the full year. It 287# is used on the footer of the generated manual pages. If in doubt, you may 288# just use %x as the value (which should be the full locale-specific date). 289my $date = enc strftime _("%B %Y"), localtime $epoch_secs; 290my $program = program_basename $ARGV[0]; 291my $package = $program; 292my $version; 293 294if ($opt_output) 295{ 296 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"), 297 $this_program, $opt_output, $! if -e $opt_output; 298 299 open STDOUT, ">$opt_output" 300 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!; 301} 302 303# The first line of the --version information is assumed to be in one 304# of the following formats: 305# 306# <version> 307# <program> <version> 308# {GNU,Free} <program> <version> 309# <program> ({GNU,Free} <package>) <version> 310# <program> - {GNU,Free} <package> <version> 311# 312# and separated from any copyright/author details by a blank line. 313 314($_, $version_text) = ((split /\n+/, $version_text, 2), ''); 315 316if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or 317 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/) 318{ 319 $program = program_basename $1; 320 $package = $2; 321 $version = $3; 322} 323elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/) 324{ 325 $program = program_basename $2; 326 $package = $1 ? "$1$program" : $program; 327 $version = $3; 328} 329else 330{ 331 $version = $_; 332} 333 334# No info for `info' itself. 335$opt_no_info = 1 if $program eq 'info'; 336 337if ($opt_name) 338{ 339 # --name overrides --include contents. 340 $replace{_('NAME')} = "$program \\- $opt_name\n"; 341} 342 343# Translators: "NAME", "SYNOPSIS" and other one or two word strings in all 344# upper case are manual page section headings. The man(1) manual page in your 345# language, if available should provide the conventional translations. 346for ($replace{_('NAME')} || ($include{_('NAME')} ||= '')) 347{ 348 if ($_) # Use first name given as $program 349 { 350 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/; 351 } 352 else # Set a default (useless) NAME paragraph. 353 { 354 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program, 355 $program, $version; 356 } 357} 358 359# Man pages traditionally have the page title in caps. 360my $PROGRAM = uc $program; 361 362# Set default page head/footers 363$source ||= "$package $version"; 364unless ($manual) 365{ 366 for ($section) 367 { 368 if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') } 369 elsif (/^6/) { $manual = enc _('Games') } 370 else { $manual = enc _('User Commands') } 371 } 372} 373 374# Extract usage clause(s) [if any] for SYNOPSIS. 375# Translators: "Usage" and "or" here are patterns (regular expressions) which 376# are used to match the usage synopsis in program output. An example from cp 377# (GNU coreutils) which contains both strings: 378# Usage: cp [OPTION]... [-T] SOURCE DEST 379# or: cp [OPTION]... SOURCE... DIRECTORY 380# or: cp [OPTION]... -t DIRECTORY SOURCE... 381my $PAT_USAGE = _('Usage'); 382my $PAT_USAGE_CONT = _('or'); 383if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om) 384{ 385 my @syn = $3 . $4; 386 387 if ($_ = $5) 388 { 389 s/^\n//; 390 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ } 391 } 392 393 my $synopsis = ''; 394 for (@syn) 395 { 396 $synopsis .= ".br\n" if $synopsis; 397 s!^\S*/!!; 398 s/^lt-// if $opt_libtool; 399 s/^(\S+) *//; 400 $synopsis .= ".B $1\n"; 401 s/\s+$//; 402 s/(([][]|\.\.+)+)/\\fR$1\\fI/g; 403 s/^/\\fI/ unless s/^\\fR//; 404 $_ .= '\fR'; 405 s/(\\fI)( *)/$2$1/g; 406 s/\\fI\\fR//g; 407 s/^\\fR//; 408 s/\\fI$//; 409 s/^\./\\&./; 410 411 $_ = fix_italic_spacing $_; 412 $synopsis .= "$_\n"; 413 } 414 415 $include{_('SYNOPSIS')} .= $synopsis; 416} 417 418# Process text, initial section is DESCRIPTION. 419my $sect = _('DESCRIPTION'); 420$_ = "$help_text\n\n$version_text"; 421 422# Normalise paragraph breaks. 423s/^\n+//; 424s/\n*$/\n/; 425s/\n\n+/\n\n/g; 426 427# Join hyphenated lines. 428s/([A-Za-z])-\n *([A-Za-z])/$1$2/g; 429 430# Temporarily exchange leading dots, apostrophes and backslashes for 431# tokens. 432s/^\./\x80/mg; 433s/^'/\x81/mg; 434s/\\/\x82/g; 435 436# Translators: patterns are used to match common program output. In the source 437# these strings are all of the form of "my $PAT_something = _('...');" and are 438# regular expressions. If there is more than one commonly used string, you 439# may separate alternatives with "|". Spaces in these expressions are written 440# as " +" to indicate that more than one space may be matched. The string 441# "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an 442# optional word, so that either "Report bugs" or "Report _program_ bugs" will 443# be matched. 444my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to'); 445my $PAT_AUTHOR = _('Written +by'); 446my $PAT_OPTIONS = _('Options'); 447my $PAT_ENVIRONMENT = _('Environment'); 448my $PAT_FILES = _('Files'); 449my $PAT_EXAMPLES = _('Examples'); 450my $PAT_FREE_SOFTWARE = _('This +is +free +software'); 451 452# Start a new paragraph (if required) for these. 453s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og; 454 455# Convert iso-8859-1 copyright symbol or (c) to nroff 456# character. 457s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg; 458 459while (length) 460{ 461 # Convert some standard paragraph names. 462 if (s/^($PAT_OPTIONS): *\n+//o) 463 { 464 $sect = _('OPTIONS'); 465 next; 466 } 467 if (s/^($PAT_ENVIRONMENT): *\n+//o) 468 { 469 $sect = _('ENVIRONMENT'); 470 next; 471 } 472 if (s/^($PAT_FILES): *\n+//o) 473 { 474 $sect = _('FILES'); 475 next; 476 } 477 elsif (s/^($PAT_EXAMPLES): *\n+//o) 478 { 479 $sect = _('EXAMPLES'); 480 next; 481 } 482 483 # Custom section indicated by a line containing "*Section Name*". 484 if (s/^\*(\w(.*\w)?)\* *\n+//) 485 { 486 $sect = uc $1; 487 $sect =~ tr/*/ /; # also accept *Section*Name* 488 push @sections, $sect; 489 next; 490 } 491 492 # Copyright section. 493 if (/^Copyright /) 494 { 495 $sect = _('COPYRIGHT'); 496 } 497 498 # Bug reporting section. 499 elsif (/^($PAT_BUGS) /o) 500 { 501 $sect = _('REPORTING BUGS'); 502 } 503 504 # Author section. 505 elsif (/^($PAT_AUTHOR)/o) 506 { 507 $sect = _('AUTHOR'); 508 } 509 510 # Examples, indicated by an indented leading $, % or > are 511 # rendered in a constant width font. 512 if (/^( +)([\$\%>] )\S/) 513 { 514 my $indent = $1; 515 my $prefix = $2; 516 my $break = '.IP'; 517 while (s/^$indent\Q$prefix\E(\S.*)\n*//) 518 { 519 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n"; 520 $break = '.br'; 521 } 522 523 next; 524 } 525 526 my $matched = ''; 527 528 # Sub-sections have a trailing colon and the second line indented. 529 if (s/^(\S.*:) *\n / /) 530 { 531 $matched .= $& if %append_match; 532 $include{$sect} .= qq(.SS "$1"\n); 533 } 534 535 my $indent = 0; 536 my $content = ''; 537 538 # Option with description. 539 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//) 540 { 541 $matched .= $& if %append_match; 542 $indent = length ($4 || "$1$3"); 543 $content = ".TP\n\x84$2\n\x84$5\n"; 544 unless ($4) 545 { 546 # Indent may be different on second line. 547 $indent = length $& if /^ {20,}/; 548 } 549 } 550 551 # Option without description. 552 elsif (s/^ {1,10}([+-]\S.*)\n//) 553 { 554 $matched .= $& if %append_match; 555 $content = ".HP\n\x84$1\n"; 556 $indent = 80; # not continued 557 } 558 559 # Indented paragraph with tag. 560 elsif (s/^( +(\S.*?))(?:( +)|\n( {20,}))(\S.*)\n//) 561 { 562 $matched .= $& if %append_match; 563 $indent = length ($4 || "$1$3"); 564 $content = ".TP\n\x84$2\n\x84$5\n"; 565 } 566 567 # Indented paragraph. 568 elsif (s/^( +)(\S.*)\n//) 569 { 570 $matched .= $& if %append_match; 571 $indent = length $1; 572 $content = ".IP\n\x84$2\n"; 573 } 574 575 # Left justified paragraph. 576 else 577 { 578 s/(.*)\n//; 579 $matched .= $& if %append_match; 580 $content = ".PP\n" if $include{$sect}; 581 $content .= "$1\n"; 582 } 583 584 # Append continuations. 585 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//) 586 { 587 $matched .= $& if %append_match; 588 $content .= "\x84$1\n"; 589 } 590 591 # Move to next paragraph. 592 s/^\n+//; 593 594 for ($content) 595 { 596 # Leading dot and apostrophe protection. 597 s/\x84\./\x80/g; 598 s/\x84'/\x81/g; 599 s/\x84//g; 600 601 # Examples should be verbatim. 602 unless ($sect eq _('EXAMPLES')) 603 { 604 # Convert options. 605 s/(^|[ (])(-[][\w=-]+)/$1 . convert_option $2/mge; 606 607 # Italicise filenames: /a/b, $VAR/c/d, ~/e/f 608 s! 609 (^|[ (]) # space/punctuation before 610 ( 611 (?:\$\w+|~)? # leading variable, or tilde 612 (?:/\w(?:[\w.-]*\w)?)+ # path components 613 ) 614 ($|[ ,;.)]) # space/punctuation after 615 !$1\\fI$2\\fP$3!xmg; 616 617 $_ = fix_italic_spacing $_; 618 } 619 620 # Escape remaining hyphens. 621 s/-/\x83/g; 622 623 if ($sect eq _('COPYRIGHT')) 624 { 625 # Insert line breaks before additional copyright messages 626 # and the disclaimer. 627 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og; 628 } 629 elsif ($sect eq _('REPORTING BUGS')) 630 { 631 # Handle multi-line bug reporting sections of the form: 632 # 633 # Report <program> bugs to <addr> 634 # GNU <package> home page: <url> 635 # ... 636 s/\n([[:upper:]])/\n.br\n$1/g; 637 } 638 } 639 640 # Check if matched paragraph contains /pat/. 641 if (%append_match) 642 { 643 for my $pat (keys %append_match) 644 { 645 if ($matched =~ $pat) 646 { 647 $content .= ".PP\n" unless $append_match{$pat} =~ /^\./; 648 $content .= $append_match{$pat}; 649 } 650 } 651 } 652 653 $include{$sect} .= $content; 654} 655 656# Refer to the real documentation. 657unless ($opt_no_info) 658{ 659 my $info_page = $opt_info || $program; 660 661 $sect = _('SEE ALSO'); 662 $include{$sect} .= ".PP\n" if $include{$sect}; 663 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page; 664The full documentation for 665.B %s 666is maintained as a Texinfo manual. If the 667.B info 668and 669.B %s 670programs are properly installed at your site, the command 671.IP 672.B info %s 673.PP 674should give you access to the complete manual. 675EOT 676} 677 678# Append additional text. 679while (my ($sect, $text) = each %append) 680{ 681 $include{$sect} .= $append{$sect}; 682} 683 684# Replace sections. 685while (my ($sect, $text) = each %replace) 686{ 687 $include{$sect} = $replace{$sect}; 688} 689 690# Output header. 691print <<EOT; 692.\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version. 693.TH $PROGRAM "$section" "$date" "$source" "$manual" 694EOT 695 696# Section ordering. 697my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS')); 698my @post = (_('ENVIRONMENT'), _('FILES'), _('EXAMPLES'), _('AUTHOR'), 699 _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO')); 700my %filter = map { $_ => 1 } @pre, @post; 701 702# Output content. 703my %done; 704for my $sect (@pre, (grep !$filter{$_}, @sections), @post) 705{ 706 next if $done{$sect}++; # ignore duplicates 707 next unless $include{$sect}; 708 if ($include{$sect}) 709 { 710 my $quote = $sect =~ /\W/ ? '"' : ''; 711 print enc ".SH $quote$sect$quote\n"; 712 713 for ($include{$sect}) 714 { 715 # Replace leading dot, apostrophe, backslash and hyphen 716 # tokens. 717 s/\x80/\\&./g; 718 s/\x81/\\&'/g; 719 s/\x82/\\e/g; 720 s/\x83/\\-/g; 721 722 # Convert some latin1 chars to troff equivalents 723 s/\xa0/\\ /g; # non-breaking space 724 725 print enc $_; 726 } 727 } 728} 729 730close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program, 731 $opt_output || 'stdout', $!; 732 733exit; 734 735# Get program basename, and strip libtool "lt-" prefix if required. 736sub program_basename 737{ 738 local $_ = shift; 739 s!.*/!!; 740 s/^lt-// if $opt_libtool; 741 $_; 742} 743 744# Call program with given option and return results. 745sub get_option_value 746{ 747 my ($prog, $opt) = @_; 748 my $stderr = $discard_stderr ? '/dev/null' : '&1'; 749 my $value = join '', 750 map { s/ +$//; expand $_ } 751 map { dec $_ } 752 `$prog $opt 2>$stderr`; 753 754 unless ($value) 755 { 756 my $err = N_("%s: can't get `%s' info from %s%s"); 757 my $extra = $discard_stderr 758 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr") 759 : ''; 760 761 kark $err, $this_program, $opt, $prog, $extra; 762 } 763 764 $value; 765} 766 767# Convert option dashes to \- to stop nroff from hyphenating 'em, and 768# embolden. Option arguments get italicised. 769sub convert_option 770{ 771 local $_ = '\fB' . shift; 772 773 s/-/\x83/g; 774 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/) 775 { 776 s/=(.)/\\fR=\\fI$1/; 777 s/ (.)/ \\fI$1/; 778 $_ .= '\fR'; 779 } 780 781 $_; 782} 783 784# Insert spacing escape characters \, and \/ before and after italic text. See 785# http://www.gnu.org/software/groff/manual/html_node/Ligatures-and-Kerning.html 786sub fix_italic_spacing 787{ 788 local $_ = shift; 789 s!\\fI(.*?)\\f([BRP])!\\fI\\,$1\\/\\f$2!g; 790 return $_; 791} 792