diff options
author | Norbert Preining <norbert@preining.info> | 2024-03-15 03:06:35 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2024-03-15 03:06:35 +0000 |
commit | 12679ab7d3c2a210f4123163671b532b8b55d5f9 (patch) | |
tree | 0060d13467186ad977f4e73488ee20dd6c0017ab /systems/texlive/tlnet/tlpkg/tlperl/lib/Pod | |
parent | 62170822e034fdd3f81de7274835d0d3b0467100 (diff) |
CTAN sync 202403150306
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/tlperl/lib/Pod')
38 files changed, 2094 insertions, 1333 deletions
diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Checker.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Checker.pm index bee20d0bfa..1dfb58b128 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Checker.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Checker.pm @@ -10,7 +10,7 @@ package Pod::Checker; use strict; use warnings; -our $VERSION = '1.74'; ## Current version of this package +our $VERSION = '1.75'; ## Current version of this package =head1 NAME @@ -1112,7 +1112,10 @@ sub new { $self->{'-line'} ||= $caller->{'_line'}; $self->{'-type'} ||= $simple_link->{'type'}; - + # preserve raw link text for additional checks + $self->{'-raw-link-text'} = (exists $simple_link->{'raw'}) + ? "$simple_link->{'raw'}" + : ""; # Force stringification of page and node. (This expands any E<>.) $self->{'-page'} = exists $simple_link->{'to'} ? "$simple_link->{'to'}" : ""; $self->{'-node'} = exists $simple_link->{'section'} ? "$simple_link->{'section'}" : ""; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Functions.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Functions.pm index f4e2a9464c..727c7fd0d4 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Functions.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Functions.pm @@ -54,11 +54,10 @@ L<perlfunc/"Perl Functions by Category"> section. =cut -our $VERSION = '1.13'; +our $VERSION = '1.14'; -require Exporter; +use Exporter 'import'; -our @ISA = qw(Exporter); our @EXPORT = qw(%Kinds %Type %Flavor %Type_Description @Type_Order); our(%Kinds, %Type, %Flavor, %Type_Description, @Type_Order); @@ -142,6 +141,7 @@ chop String remove the last character from a string chown File change the ownership on a list of files chr String get character this number represents chroot File make directory new root for path lookups +class Namespace Objects declare a separate global namespace that is an object class close I/O close file (or pipe or socket) handle closedir I/O close directory handle connect Socket connect to a remote socket @@ -171,6 +171,7 @@ exit Flow terminate this program exp Math raise I<e> to a power fc String return casefolded version of a string fcntl File file control system call +field Namespace Objects declare a field variable of the current class __FILE__ Flow the name of the current source file fileno I/O return file descriptor from filehandle flock I/O lock an entire file with an advisory lock @@ -229,6 +230,7 @@ log Math retrieve the natural logarithm for a number lstat File stat a symbolic link m// Regexp match a string with a regular expression pattern map LIST apply a change to a list to get back a new list with the changes +method Flow Objects declare a method of a class mkdir File create a directory msgctl SysV SysV IPC message control operations msgget SysV get SysV IPC message queue @@ -332,14 +334,14 @@ times Process Time return elapsed time for self and child processes tr/// String transliterate a string truncate I/O shorten a file uc String return upper-case version of a string -ucfirst String return a string with just the next letter in upper case +ucfirst String return a string with the first letter in upper case umask File set file creation mode mask undef Misc remove a variable or function definition unlink File remove one link to a file unpack Binary LIST convert binary structure into normal perl variables unshift ARRAY prepend more elements to the beginning of a list untie Objects break a tie binding to a variable -use Modules Namespace Objects load in a module at compile time and import its namespace +use Modules Namespace Objects enable Perl language features and declare required version utime File set a file's last access and modify times values ARRAY HASH return a list of the values in a hash vec Binary test or set particular bits in a string diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html.pm index ba0ab0b39a..7c568f9e91 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html.pm @@ -1,22 +1,27 @@ package Pod::Html; use strict; -require Exporter; +use Exporter 'import'; -our $VERSION = 1.27; -our @ISA = qw(Exporter); -our @EXPORT = qw(pod2html htmlify); -our @EXPORT_OK = qw(anchorify relativize_url); +our $VERSION = 1.34; +$VERSION = eval $VERSION; +our @EXPORT = qw(pod2html); -use Carp; use Config; use Cwd; use File::Basename; use File::Spec; -use File::Spec::Unix; -use Getopt::Long; use Pod::Simple::Search; use Pod::Simple::SimpleTree (); -use Text::Tabs; +use Pod::Html::Util qw( + html_escape + process_command_line + trim_leading_whitespace + unixify + usage + htmlify + anchorify + relativize_url +); use locale; # make \w work right in non-ASCII lands =head1 NAME @@ -189,20 +194,26 @@ Display progress messages. By default, they won't be displayed. =back -=head2 htmlify +=head2 Formerly Exported Auxiliary Functions - htmlify($heading); +Prior to perl-5.36, the following three functions were exported by +F<Pod::Html>, either by default or on request: + +=over 4 -Converts a pod section specification to a suitable section specification -for HTML. Note that we keep spaces and special characters except -C<", ?> (Netscape problem) and the hyphen (writer's problem...). +=item * C<htmlify()> (by default) -=head2 anchorify +=item * C<anchorify()> (upon request) + +=item * C<relativize_url()> (upon request) + +=back - anchorify(@heading); +The definition and documentation of these functions have been moved to +F<Pod::Html::Util>, viewable via C<perldoc Pod::Html::Util>. -Similar to C<htmlify()>, but turns non-alphanumerics into underscores. Note -that C<anchorify()> is not exported by default. +Beginning with perl-5.38 these functions must be explicitly imported from +F<Pod::Html::Util>. Please modify your code as needed. =head1 ENVIRONMENT @@ -224,386 +235,234 @@ This program is distributed under the Artistic License. =cut -# This sub duplicates the guts of Pod::Simple::FromTree. We could have -# used that module, except that it would have been a non-core dependency. -sub feed_tree_to_parser { - my($parser, $tree) = @_; - if(ref($tree) eq "") { - $parser->_handle_text($tree); - } elsif(!($tree->[0] eq "X" && $parser->nix_X_codes)) { - $parser->_handle_element_start($tree->[0], $tree->[1]); - feed_tree_to_parser($parser, $_) foreach @{$tree}[2..$#$tree]; - $parser->_handle_element_end($tree->[0]); - } -} - -my $Cachedir; -my $Dircache; -my($Htmlroot, $Htmldir, $Htmlfile, $Htmlfileurl); -my($Podfile, @Podpath, $Podroot); -my $Poderrors; -my $Css; - -my $Recurse; -my $Quiet; -my $Verbose; -my $Doindex; - -my $Backlink; - -my($Title, $Header); - -my %Pages = (); # associative array used to find the location - # of pages referenced by L<> links. - -my $Curdir = File::Spec->curdir; - -sub init_globals { - $Cachedir = "."; # The directory to which directory caches - # will be written. - - $Dircache = "pod2htmd.tmp"; - - $Htmlroot = "/"; # http-server base directory from which all - # relative paths in $podpath stem. - $Htmldir = ""; # The directory to which the html pages - # will (eventually) be written. - $Htmlfile = ""; # write to stdout by default - $Htmlfileurl = ""; # The url that other files would use to - # refer to this file. This is only used - # to make relative urls that point to - # other files. - - $Poderrors = 1; - $Podfile = ""; # read from stdin by default - @Podpath = (); # list of directories containing library pods. - $Podroot = $Curdir; # filesystem base directory from which all - # relative paths in $podpath stem. - $Css = ''; # Cascading style sheet - $Recurse = 1; # recurse on subdirectories in $podpath. - $Quiet = 0; # not quiet by default - $Verbose = 0; # not verbose by default - $Doindex = 1; # non-zero if we should generate an index - $Backlink = 0; # no backlinks added by default - $Header = 0; # produce block header/footer - $Title = undef; # title to give the pod(s) +sub new { + my $class = shift; + return bless {}, $class; } sub pod2html { local(@ARGV) = @_; local $_; - init_globals(); - parse_command_line(); + my $self = Pod::Html->new(); + $self->init_globals(); - # prevent '//' in urls - $Htmlroot = "" if $Htmlroot eq "/"; - $Htmldir =~ s#/\z##; + my $opts = process_command_line; + $self->process_options($opts); - if ( $Htmlroot eq '' - && defined( $Htmldir ) - && $Htmldir ne '' - && substr( $Htmlfile, 0, length( $Htmldir ) ) eq $Htmldir - ) { - # Set the 'base' url for this file, so that we can use it - # as the location from which to calculate relative links - # to other files. If this is '', then absolute links will - # be used throughout. - #$Htmlfileurl = "$Htmldir/" . substr( $Htmlfile, length( $Htmldir ) + 1); - # Is the above not just "$Htmlfileurl = $Htmlfile"? - $Htmlfileurl = Pod::Html::_unixify($Htmlfile); - - } + $self->refine_globals(); # load or generate/cache %Pages - unless (get_cache($Dircache, \@Podpath, $Podroot, $Recurse)) { + unless ($self->get_cache()) { # generate %Pages - my $pwd = getcwd(); - chdir($Podroot) || - die "$0: error changing to directory $Podroot: $!\n"; - - # find all pod modules/pages in podpath, store in %Pages - # - callback used to remove Podroot and extension from each file - # - laborious to allow '.' in dirnames (e.g., /usr/share/perl/5.14.1) - Pod::Simple::Search->new->inc(0)->verbose($Verbose)->laborious(1) - ->callback(\&_save_page)->recurse($Recurse)->survey(@Podpath); - - chdir($pwd) || die "$0: error changing to directory $pwd: $!\n"; - - # cache the directory list for later use - warn "caching directories for later use\n" if $Verbose; - open my $cache, '>', $Dircache - or die "$0: error open $Dircache for writing: $!\n"; - - print $cache join(":", @Podpath) . "\n$Podroot\n"; - my $_updirs_only = ($Podroot =~ /\.\./) && !($Podroot =~ /[^\.\\\/]/); - foreach my $key (keys %Pages) { - if($_updirs_only) { - my $_dirlevel = $Podroot; - while($_dirlevel =~ /\.\./) { - $_dirlevel =~ s/\.\.//; - # Assume $Pages{$key} has '/' separators (html dir separators). - $Pages{$key} =~ s/^[\w\s\-\.]+\///; - } - } - print $cache "$key $Pages{$key}\n"; - } - - close $cache or die "error closing $Dircache: $!"; + #%Pages = $self->generate_cache(\%Pages); + $self->generate_cache($self->{Pages}); } - - my $input; - unless (@ARGV && $ARGV[0]) { - if ($Podfile and $Podfile ne '-') { - $input = $Podfile; - } else { - $input = '-'; # XXX: make a test case for this - } - } else { - $Podfile = $ARGV[0]; - $input = *ARGV; - } - - # set options for input parser - my $parser = Pod::Simple::SimpleTree->new; - # Normalize whitespace indenting - $parser->strip_verbatim_indent(\&trim_leading_whitespace); - - $parser->codes_in_verbatim(0); - $parser->accept_targets(qw(html HTML)); - $parser->no_errata_section(!$Poderrors); # note the inverse - - warn "Converting input file $Podfile\n" if $Verbose; - my $podtree = $parser->parse_file($input)->root; - - unless(defined $Title) { - if($podtree->[0] eq "Document" && ref($podtree->[2]) eq "ARRAY" && - $podtree->[2]->[0] eq "head1" && @{$podtree->[2]} == 3 && - ref($podtree->[2]->[2]) eq "" && $podtree->[2]->[2] eq "NAME" && - ref($podtree->[3]) eq "ARRAY" && $podtree->[3]->[0] eq "Para" && - @{$podtree->[3]} >= 3 && - !(grep { ref($_) ne "" } - @{$podtree->[3]}[2..$#{$podtree->[3]}]) && - (@$podtree == 4 || - (ref($podtree->[4]) eq "ARRAY" && - $podtree->[4]->[0] eq "head1"))) { - $Title = join("", @{$podtree->[3]}[2..$#{$podtree->[3]}]); - } - } - - $Title //= ""; - $Title = html_escape($Title); + my $input = $self->identify_input(); + my $podtree = $self->parse_input_for_podtree($input); + $self->set_Title_from_podtree($podtree); # set options for the HTML generator - $parser = Pod::Simple::XHTML::LocalPodLinks->new(); + my $parser = Pod::Simple::XHTML::LocalPodLinks->new(); $parser->codes_in_verbatim(0); $parser->anchor_items(1); # the old Pod::Html always did - $parser->backlink($Backlink); # linkify =head1 directives - $parser->force_title($Title); - $parser->htmldir($Htmldir); - $parser->htmlfileurl($Htmlfileurl); - $parser->htmlroot($Htmlroot); - $parser->index($Doindex); - $parser->output_string(\my $output); # written to file later - $parser->pages(\%Pages); - $parser->quiet($Quiet); - $parser->verbose($Verbose); + $parser->backlink($self->{Backlink}); # linkify =head1 directives + $parser->force_title($self->{Title}); + $parser->htmldir($self->{Htmldir}); + $parser->htmlfileurl($self->{Htmlfileurl}); + $parser->htmlroot($self->{Htmlroot}); + $parser->index($self->{Doindex}); + $parser->output_string(\$self->{output}); # written to file later + #$parser->pages(\%Pages); + $parser->pages($self->{Pages}); + $parser->quiet($self->{Quiet}); + $parser->verbose($self->{Verbose}); + + $parser = $self->refine_parser($parser); + $self->feed_tree_to_parser($parser, $podtree); + $self->write_file(); +} - # We need to add this ourselves because we use our own header, not - # ::XHTML's header. We need to set $parser->backlink to linkify - # the =head1 directives - my $bodyid = $Backlink ? ' id="_podtop_"' : ''; +sub init_globals { + my $self = shift; + $self->{Cachedir} = "."; # The directory to which directory caches + # will be written. + + $self->{Dircache} = "pod2htmd.tmp"; + + $self->{Htmlroot} = "/"; # http-server base directory from which all + # relative paths in $podpath stem. + $self->{Htmldir} = ""; # The directory to which the html pages + # will (eventually) be written. + $self->{Htmlfile} = ""; # write to stdout by default + $self->{Htmlfileurl} = ""; # The url that other files would use to + # refer to this file. This is only used + # to make relative urls that point to + # other files. + + $self->{Poderrors} = 1; + $self->{Podfile} = ""; # read from stdin by default + $self->{Podpath} = []; # list of directories containing library pods. + $self->{Podroot} = $self->{Curdir} = File::Spec->curdir; + # filesystem base directory from which all + # relative paths in $podpath stem. + $self->{Css} = ''; # Cascading style sheet + $self->{Recurse} = 1; # recurse on subdirectories in $podpath. + $self->{Quiet} = 0; # not quiet by default + $self->{Verbose} = 0; # not verbose by default + $self->{Doindex} = 1; # non-zero if we should generate an index + $self->{Backlink} = 0; # no backlinks added by default + $self->{Header} = 0; # produce block header/footer + $self->{Title} = undef; # title to give the pod(s) + $self->{Saved_Cache_Key} = ''; + $self->{Pages} = {}; + return $self; +} - my $csslink = ''; - my $tdstyle = ' style="background-color: #cccccc; color: #000"'; +sub process_options { + my ($self, $opts) = @_; + + $self->{Podpath} = (defined $opts->{podpath}) + ? [ split(":", $opts->{podpath}) ] + : []; + + $self->{Backlink} = $opts->{backlink} if defined $opts->{backlink}; + $self->{Cachedir} = unixify($opts->{cachedir}) if defined $opts->{cachedir}; + $self->{Css} = $opts->{css} if defined $opts->{css}; + $self->{Header} = $opts->{header} if defined $opts->{header}; + $self->{Htmldir} = unixify($opts->{htmldir}) if defined $opts->{htmldir}; + $self->{Htmlroot} = unixify($opts->{htmlroot}) if defined $opts->{htmlroot}; + $self->{Doindex} = $opts->{index} if defined $opts->{index}; + $self->{Podfile} = unixify($opts->{infile}) if defined $opts->{infile}; + $self->{Htmlfile} = unixify($opts->{outfile}) if defined $opts->{outfile}; + $self->{Poderrors} = $opts->{poderrors} if defined $opts->{poderrors}; + $self->{Podroot} = unixify($opts->{podroot}) if defined $opts->{podroot}; + $self->{Quiet} = $opts->{quiet} if defined $opts->{quiet}; + $self->{Recurse} = $opts->{recurse} if defined $opts->{recurse}; + $self->{Title} = $opts->{title} if defined $opts->{title}; + $self->{Verbose} = $opts->{verbose} if defined $opts->{verbose}; - if ($Css) { - $csslink = qq(\n<link rel="stylesheet" href="$Css" type="text/css" />); - $csslink =~ s,\\,/,g; - $csslink =~ s,(/.):,$1|,; - $tdstyle= ''; + warn "Flushing directory caches\n" + if $opts->{verbose} && defined $opts->{flush}; + $self->{Dircache} = "$self->{Cachedir}/pod2htmd.tmp"; + if (defined $opts->{flush}) { + 1 while unlink($self->{Dircache}); } + return $self; +} - # header/footer block - my $block = $Header ? <<END_OF_BLOCK : ''; -<table border="0" width="100%" cellspacing="0" cellpadding="3"> -<tr><td class="_podblock_"$tdstyle valign="middle"> -<big><strong><span class="_podblock_"> $Title</span></strong></big> -</td></tr> -</table> -END_OF_BLOCK - - # create own header/footer because of --header - $parser->html_header(<<"HTMLHEAD"); -<?xml version="1.0" ?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<title>$Title</title>$csslink -<meta http-equiv="content-type" content="text/html; charset=utf-8" /> -<link rev="made" href="mailto:$Config{perladmin}" /> -</head> - -<body$bodyid> -$block -HTMLHEAD - - $parser->html_footer(<<"HTMLFOOT"); -$block -</body> - -</html> -HTMLFOOT +sub refine_globals { + my $self = shift; - feed_tree_to_parser($parser, $podtree); + # prevent '//' in urls + $self->{Htmlroot} = "" if $self->{Htmlroot} eq "/"; + $self->{Htmldir} =~ s#/\z##; - # Write output to file - $Htmlfile = "-" unless $Htmlfile; # stdout - my $fhout; - if($Htmlfile and $Htmlfile ne '-') { - open $fhout, ">", $Htmlfile - or die "$0: cannot open $Htmlfile file for output: $!\n"; - } else { - open $fhout, ">-"; + if ( $self->{Htmlroot} eq '' + && defined( $self->{Htmldir} ) + && $self->{Htmldir} ne '' + && substr( $self->{Htmlfile}, 0, length( $self->{Htmldir} ) ) eq $self->{Htmldir} + ) { + # Set the 'base' url for this file, so that we can use it + # as the location from which to calculate relative links + # to other files. If this is '', then absolute links will + # be used throughout. + #$self->{Htmlfileurl} = "$self->{Htmldir}/" . substr( $self->{Htmlfile}, length( $self->{Htmldir} ) + 1); + # Is the above not just "$self->{Htmlfileurl} = $self->{Htmlfile}"? + $self->{Htmlfileurl} = unixify($self->{Htmlfile}); } - binmode $fhout, ":utf8"; - print $fhout $output; - close $fhout or die "Failed to close $Htmlfile: $!"; - chmod 0644, $Htmlfile unless $Htmlfile eq '-'; + return $self; } -############################################################################## - -sub usage { - my $podfile = shift; - warn "$0: $podfile: @_\n" if @_; - die <<END_OF_USAGE; -Usage: $0 --help --htmldir=<name> --htmlroot=<URL> - --infile=<name> --outfile=<name> - --podpath=<name>:...:<name> --podroot=<name> - --cachedir=<name> --flush --recurse --norecurse - --quiet --noquiet --verbose --noverbose - --index --noindex --backlink --nobacklink - --header --noheader --poderrors --nopoderrors - --css=<URL> --title=<name> - - --[no]backlink - turn =head1 directives into links pointing to the top of - the page (off by default). - --cachedir - directory for the directory cache files. - --css - stylesheet URL - --flush - flushes the directory cache. - --[no]header - produce block header/footer (default is no headers). - --help - prints this message. - --htmldir - directory for resulting HTML files. - --htmlroot - http-server base directory from which all relative paths - in podpath stem (default is /). - --[no]index - generate an index at the top of the resulting html - (default behaviour). - --infile - filename for the pod to convert (input taken from stdin - by default). - --outfile - filename for the resulting html file (output sent to - stdout by default). - --[no]poderrors - include a POD ERRORS section in the output if there were - any POD errors in the input (default behavior). - --podpath - colon-separated list of directories containing library - pods (empty by default). - --podroot - filesystem base directory from which all relative paths - in podpath stem (default is .). - --[no]quiet - suppress some benign warning messages (default is off). - --[no]recurse - recurse on those subdirectories listed in podpath - (default behaviour). - --title - title that will appear in resulting html file. - --[no]verbose - self-explanatory (off by default). - -END_OF_USAGE +sub generate_cache { + my $self = shift; + my $pwd = getcwd(); + chdir($self->{Podroot}) || + die "$0: error changing to directory $self->{Podroot}: $!\n"; + + # find all pod modules/pages in podpath, store in %Pages + # - inc(0): do not prepend directories in @INC to search list; + # limit search to those in @{$self->{Podpath}} + # - verbose: report (via 'warn') what search is doing + # - laborious: to allow '.' in dirnames (e.g., /usr/share/perl/5.14.1) + # - recurse: go into subdirectories + # - survey: search for POD files in PodPath + my ($name2path, $path2name) = + Pod::Simple::Search->new->inc(0)->verbose($self->{Verbose})->laborious(1) + ->recurse($self->{Recurse})->survey(@{$self->{Podpath}}); + # remove Podroot and extension from each file + for my $k (keys %{$name2path}) { + $self->{Pages}{$k} = _transform($self, $name2path->{$k}); + } + chdir($pwd) || die "$0: error changing to directory $pwd: $!\n"; + + # cache the directory list for later use + warn "caching directories for later use\n" if $self->{Verbose}; + open my $cache, '>', $self->{Dircache} + or die "$0: error open $self->{Dircache} for writing: $!\n"; + + print $cache join(":", @{$self->{Podpath}}) . "\n$self->{Podroot}\n"; + my $_updirs_only = ($self->{Podroot} =~ /\.\./) && !($self->{Podroot} =~ /[^\.\\\/]/); + foreach my $key (keys %{$self->{Pages}}) { + if($_updirs_only) { + my $_dirlevel = $self->{Podroot}; + while($_dirlevel =~ /\.\./) { + $_dirlevel =~ s/\.\.//; + # Assume $Pagesref->{$key} has '/' separators (html dir separators). + $self->{Pages}->{$key} =~ s/^[\w\s\-\.]+\///; + } + } + print $cache "$key $self->{Pages}->{$key}\n"; + } + close $cache or die "error closing $self->{Dircache}: $!"; } -sub parse_command_line { - my ($opt_backlink,$opt_cachedir,$opt_css,$opt_flush,$opt_header, - $opt_help,$opt_htmldir,$opt_htmlroot,$opt_index,$opt_infile, - $opt_outfile,$opt_poderrors,$opt_podpath,$opt_podroot, - $opt_quiet,$opt_recurse,$opt_title,$opt_verbose); - - unshift @ARGV, split ' ', $Config{pod2html} if $Config{pod2html}; - my $result = GetOptions( - 'backlink!' => \$opt_backlink, - 'cachedir=s' => \$opt_cachedir, - 'css=s' => \$opt_css, - 'flush' => \$opt_flush, - 'help' => \$opt_help, - 'header!' => \$opt_header, - 'htmldir=s' => \$opt_htmldir, - 'htmlroot=s' => \$opt_htmlroot, - 'index!' => \$opt_index, - 'infile=s' => \$opt_infile, - 'outfile=s' => \$opt_outfile, - 'poderrors!' => \$opt_poderrors, - 'podpath=s' => \$opt_podpath, - 'podroot=s' => \$opt_podroot, - 'quiet!' => \$opt_quiet, - 'recurse!' => \$opt_recurse, - 'title=s' => \$opt_title, - 'verbose!' => \$opt_verbose, - ); - usage("-", "invalid parameters") if not $result; - - usage("-") if defined $opt_help; # see if the user asked for help - $opt_help = ""; # just to make -w shut-up. - - @Podpath = split(":", $opt_podpath) if defined $opt_podpath; - - $Backlink = $opt_backlink if defined $opt_backlink; - $Cachedir = _unixify($opt_cachedir) if defined $opt_cachedir; - $Css = $opt_css if defined $opt_css; - $Header = $opt_header if defined $opt_header; - $Htmldir = _unixify($opt_htmldir) if defined $opt_htmldir; - $Htmlroot = _unixify($opt_htmlroot) if defined $opt_htmlroot; - $Doindex = $opt_index if defined $opt_index; - $Podfile = _unixify($opt_infile) if defined $opt_infile; - $Htmlfile = _unixify($opt_outfile) if defined $opt_outfile; - $Poderrors = $opt_poderrors if defined $opt_poderrors; - $Podroot = _unixify($opt_podroot) if defined $opt_podroot; - $Quiet = $opt_quiet if defined $opt_quiet; - $Recurse = $opt_recurse if defined $opt_recurse; - $Title = $opt_title if defined $opt_title; - $Verbose = $opt_verbose if defined $opt_verbose; +sub _transform { + my ($self, $v) = @_; + $v = $self->{Podroot} eq File::Spec->curdir + ? File::Spec->abs2rel($v) + : File::Spec->abs2rel($v, + File::Spec->canonpath($self->{Podroot})); - warn "Flushing directory caches\n" - if $opt_verbose && defined $opt_flush; - $Dircache = "$Cachedir/pod2htmd.tmp"; - if (defined $opt_flush) { - 1 while unlink($Dircache); - } -} + # Convert path to unix style path + $v = unixify($v); -my $Saved_Cache_Key; + my ($file, $dir) = fileparse($v, qr/\.[^.]*/); # strip .ext + return $dir.$file; +} sub get_cache { - my($dircache, $podpath, $podroot, $recurse) = @_; + my $self = shift; # A first-level cache: # Don't bother reading the cache files if they still apply # and haven't changed since we last read them. - my $this_cache_key = cache_key($dircache, $podpath, $podroot, $recurse); - return 1 if $Saved_Cache_Key and $this_cache_key eq $Saved_Cache_Key; - $Saved_Cache_Key = $this_cache_key; + my $this_cache_key = $self->cache_key(); + return 1 if $self->{Saved_Cache_Key} and $this_cache_key eq $self->{Saved_Cache_Key}; + $self->{Saved_Cache_Key} = $this_cache_key; # load the cache of %Pages if possible. $tests will be # non-zero if successful. my $tests = 0; - if (-f $dircache) { - warn "scanning for directory cache\n" if $Verbose; - $tests = load_cache($dircache, $podpath, $podroot); + if (-f $self->{Dircache}) { + warn "scanning for directory cache\n" if $self->{Verbose}; + $tests = $self->load_cache(); } return $tests; } sub cache_key { - my($dircache, $podpath, $podroot, $recurse) = @_; - return join('!',$dircache,$recurse,@$podpath,$podroot,stat($dircache)); + my $self = shift; + return join('!', + $self->{Dircache}, + $self->{Recurse}, + @{$self->{Podpath}}, + $self->{Podroot}, + stat($self->{Dircache}), + ); } # @@ -611,24 +470,24 @@ sub cache_key { # cache of %Pages. if so, it loads them and returns a non-zero value. # sub load_cache { - my($dircache, $podpath, $podroot) = @_; + my $self = shift; my $tests = 0; local $_; - warn "scanning for directory cache\n" if $Verbose; - open(my $cachefh, '<', $dircache) || - die "$0: error opening $dircache for reading: $!\n"; + warn "scanning for directory cache\n" if $self->{Verbose}; + open(my $cachefh, '<', $self->{Dircache}) || + die "$0: error opening $self->{Dircache} for reading: $!\n"; $/ = "\n"; # is it the same podpath? $_ = <$cachefh>; chomp($_); - $tests++ if (join(":", @$podpath) eq $_); + $tests++ if (join(":", @{$self->{Podpath}}) eq $_); # is it the same podroot? $_ = <$cachefh>; chomp($_); - $tests++ if ($podroot eq $_); + $tests++ if ($self->{Podroot} eq $_); # load the cache if its good if ($tests != 2) { @@ -636,96 +495,147 @@ sub load_cache { return 0; } - warn "loading directory cache\n" if $Verbose; + warn "loading directory cache\n" if $self->{Verbose}; while (<$cachefh>) { /(.*?) (.*)$/; - $Pages{$1} = $2; + $self->{Pages}->{$1} = $2; } close($cachefh); return 1; } - -# -# html_escape: make text safe for HTML -# -sub html_escape { - my $rest = $_[0]; - $rest =~ s/&/&/g; - $rest =~ s/</</g; - $rest =~ s/>/>/g; - $rest =~ s/"/"/g; - $rest =~ s/([[:^print:]])/sprintf("&#x%x;", ord($1))/aeg; - return $rest; +sub identify_input { + my $self = shift; + my $input; + unless (@ARGV && $ARGV[0]) { + if ($self->{Podfile} and $self->{Podfile} ne '-') { + $input = $self->{Podfile}; + } else { + $input = '-'; # XXX: make a test case for this + } + } else { + $self->{Podfile} = $ARGV[0]; + $input = *ARGV; + } + return $input; } -# -# htmlify - converts a pod section specification to a suitable section -# specification for HTML. We adopt the mechanism used by the formatter -# that we use. -# -sub htmlify { - my( $heading) = @_; - return Pod::Simple::XHTML->can("idify")->(undef, $heading, 1); +sub parse_input_for_podtree { + my ($self, $input) = @_; + # set options for input parser + my $input_parser = Pod::Simple::SimpleTree->new; + # Normalize whitespace indenting + $input_parser->strip_verbatim_indent(\&trim_leading_whitespace); + + $input_parser->codes_in_verbatim(0); + $input_parser->accept_targets(qw(html HTML)); + $input_parser->no_errata_section(!$self->{Poderrors}); # note the inverse + + warn "Converting input file $self->{Podfile}\n" if $self->{Verbose}; + my $podtree = $input_parser->parse_file($input)->root; + return $podtree; } -# -# similar to htmlify, but turns non-alphanumerics into underscores -# -sub anchorify { - my ($anchor) = @_; - $anchor = htmlify($anchor); - $anchor =~ s/\W/_/g; - return $anchor; +sub set_Title_from_podtree { + my ($self, $podtree) = @_; + unless(defined $self->{Title}) { + if($podtree->[0] eq "Document" && ref($podtree->[2]) eq "ARRAY" && + $podtree->[2]->[0] eq "head1" && @{$podtree->[2]} == 3 && + ref($podtree->[2]->[2]) eq "" && $podtree->[2]->[2] eq "NAME" && + ref($podtree->[3]) eq "ARRAY" && $podtree->[3]->[0] eq "Para" && + @{$podtree->[3]} >= 3 && + !(grep { ref($_) ne "" } + @{$podtree->[3]}[2..$#{$podtree->[3]}]) && + (@$podtree == 4 || + (ref($podtree->[4]) eq "ARRAY" && + $podtree->[4]->[0] eq "head1"))) { + $self->{Title} = join("", @{$podtree->[3]}[2..$#{$podtree->[3]}]); + } + } + + $self->{Title} //= ""; + $self->{Title} = html_escape($self->{Title}); + return $self; } -# -# store POD files in %Pages -# -sub _save_page { - my ($modspec, $modname) = @_; +sub refine_parser { + my ($self, $parser) = @_; + # We need to add this ourselves because we use our own header, not + # ::XHTML's header. We need to set $parser->backlink to linkify + # the =head1 directives + my $bodyid = $self->{Backlink} ? ' id="_podtop_"' : ''; - # Remove Podroot from path - $modspec = $Podroot eq File::Spec->curdir - ? File::Spec->abs2rel($modspec) - : File::Spec->abs2rel($modspec, - File::Spec->canonpath($Podroot)); + my $csslink = ''; + my $tdstyle = ' style="background-color: #cccccc; color: #000"'; - # Convert path to unix style path - $modspec = Pod::Html::_unixify($modspec); + if ($self->{Css}) { + $csslink = qq(\n<link rel="stylesheet" href="$self->{Css}" type="text/css" />); + $csslink =~ s,\\,/,g; + $csslink =~ s,(/.):,$1|,; + $tdstyle= ''; + } + + # header/footer block + my $block = $self->{Header} ? <<END_OF_BLOCK : ''; +<table border="0" width="100%" cellspacing="0" cellpadding="3"> +<tr><td class="_podblock_"$tdstyle valign="middle"> +<big><strong><span class="_podblock_"> $self->{Title}</span></strong></big> +</td></tr> +</table> +END_OF_BLOCK + + # create own header/footer because of --header + $parser->html_header(<<"HTMLHEAD"); +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>$self->{Title}</title>$csslink +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<link rev="made" href="mailto:$Config{perladmin}" /> +</head> + +<body$bodyid> +$block +HTMLHEAD + + $parser->html_footer(<<"HTMLFOOT"); +$block +</body> - my ($file, $dir) = fileparse($modspec, qr/\.[^.]*/); # strip .ext - $Pages{$modname} = $dir.$file; +</html> +HTMLFOOT + return $parser; } -sub _unixify { - my $full_path = shift; - return '' unless $full_path; - return $full_path if $full_path eq '/'; - - my ($vol, $dirs, $file) = File::Spec->splitpath($full_path); - my @dirs = $dirs eq File::Spec->curdir() - ? (File::Spec::Unix->curdir()) - : File::Spec->splitdir($dirs); - if (defined($vol) && $vol) { - $vol =~ s/:$// if $^O eq 'VMS'; - $vol = uc $vol if $^O eq 'MSWin32'; - - if( $dirs[0] ) { - unshift @dirs, $vol; - } - else { - $dirs[0] = $vol; - } +# This sub duplicates the guts of Pod::Simple::FromTree. We could have +# used that module, except that it would have been a non-core dependency. +sub feed_tree_to_parser { + my($self, $parser, $tree) = @_; + if(ref($tree) eq "") { + $parser->_handle_text($tree); + } elsif(!($tree->[0] eq "X" && $parser->nix_X_codes)) { + $parser->_handle_element_start($tree->[0], $tree->[1]); + $self->feed_tree_to_parser($parser, $_) foreach @{$tree}[2..$#$tree]; + $parser->_handle_element_end($tree->[0]); } - unshift @dirs, '' if File::Spec->file_name_is_absolute($full_path); - return $file unless scalar(@dirs); - $full_path = File::Spec::Unix->catfile(File::Spec::Unix->catdir(@dirs), - $file); - $full_path =~ s|^\/|| if $^O eq 'MSWin32'; # C:/foo works, /C:/foo doesn't - $full_path =~ s/\^\././g if $^O eq 'VMS'; # unescape dots - return $full_path; +} + +sub write_file { + my $self = shift; + $self->{Htmlfile} = "-" unless $self->{Htmlfile}; # stdout + my $fhout; + if($self->{Htmlfile} and $self->{Htmlfile} ne '-') { + open $fhout, ">", $self->{Htmlfile} + or die "$0: cannot open $self->{Htmlfile} file for output: $!\n"; + } else { + open $fhout, ">-"; + } + binmode $fhout, ":utf8"; + print $fhout $self->{output}; + close $fhout or die "Failed to close $self->{Htmlfile}: $!"; + chmod 0644, $self->{Htmlfile} unless $self->{Htmlfile} eq '-'; } package Pod::Simple::XHTML::LocalPodLinks; @@ -795,15 +705,15 @@ sub resolve_pod_page_link { $path = $self->pages->{$to}; } - my $url = File::Spec::Unix->catfile(Pod::Html::_unixify($self->htmlroot), + my $url = File::Spec::Unix->catfile(Pod::Html::Util::unixify($self->htmlroot), $path); if ($self->htmlfileurl ne '') { # then $self->htmlroot eq '' (by definition of htmlfileurl) so # $self->htmldir needs to be prepended to link to get the absolute path # that will be relativized - $url = Pod::Html::relativize_url( - File::Spec::Unix->catdir(Pod::Html::_unixify($self->htmldir), $url), + $url = Pod::Html::Util::relativize_url( + File::Spec::Unix->catdir(Pod::Html::Util::unixify($self->htmldir), $url), $self->htmlfileurl # already unixified ); } @@ -811,56 +721,4 @@ sub resolve_pod_page_link { return $url . ".html$section"; } -package Pod::Html; - -# -# relativize_url - convert an absolute URL to one relative to a base URL. -# Assumes both end in a filename. -# -sub relativize_url { - my ($dest, $source) = @_; - - # Remove each file from its path - my ($dest_volume, $dest_directory, $dest_file) = - File::Spec::Unix->splitpath( $dest ); - $dest = File::Spec::Unix->catpath( $dest_volume, $dest_directory, '' ); - - my ($source_volume, $source_directory, $source_file) = - File::Spec::Unix->splitpath( $source ); - $source = File::Spec::Unix->catpath( $source_volume, $source_directory, '' ); - - my $rel_path = ''; - if ($dest ne '') { - $rel_path = File::Spec::Unix->abs2rel( $dest, $source ); - } - - if ($rel_path ne '' && substr( $rel_path, -1 ) ne '/') { - $rel_path .= "/$dest_file"; - } else { - $rel_path .= "$dest_file"; - } - - return $rel_path; -} - -# Remove any level of indentation (spaces or tabs) from each code block consistently -# Adapted from: https://metacpan.org/source/HAARG/MetaCPAN-Pod-XHTML-0.002001/lib/Pod/Simple/Role/StripVerbatimIndent.pm -sub trim_leading_whitespace { - my ($para) = @_; - - # Start by converting tabs to spaces - @$para = Text::Tabs::expand(@$para); - - # Find the line with the least amount of indent, as that's our "base" - my @indent_levels = (sort(map { $_ =~ /^( *)./mg } @$para)); - my $indent = $indent_levels[0] || ""; - - # Remove the "base" amount of indent from each line - foreach (@$para) { - $_ =~ s/^\Q$indent//mg; - } - - return; -} - 1; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html/Util.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html/Util.pm new file mode 100755 index 0000000000..88452d4d4e --- /dev/null +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Html/Util.pm @@ -0,0 +1,282 @@ +package Pod::Html::Util; +use strict; +use Exporter 'import'; + +our $VERSION = 1.34; # Please keep in synch with lib/Pod/Html.pm +$VERSION = eval $VERSION; +our @EXPORT_OK = qw( + anchorify + html_escape + htmlify + process_command_line + relativize_url + trim_leading_whitespace + unixify + usage +); + +use Config; +use File::Spec; +use File::Spec::Unix; +use Getopt::Long; +use Pod::Simple::XHTML; +use Text::Tabs; +use locale; # make \w work right in non-ASCII lands + +=head1 NAME + +Pod::Html::Util - helper functions for Pod-Html + +=head1 SUBROUTINES + +B<Note:> While these functions are importable on request from +F<Pod::Html::Util>, they are specifically intended for use within (a) the +F<Pod-Html> distribution (modules and test programs) shipped as part of the +Perl 5 core and (b) other parts of the core such as the F<installhtml> +program. These functions may be modified or relocated within the core +distribution -- or removed entirely therefrom -- as the core's needs evolve. +Hence, you should not rely on these functions in situations other than those +just described. + +=cut + +=head2 C<process_command_line()> + +Process command-line switches (options). Returns a reference to a hash. Will +provide usage message if C<--help> switch is present or if parameters are +invalid. + +Calling this subroutine may modify C<@ARGV>. + +=cut + +sub process_command_line { + my %opts = map { $_ => undef } (qw| + backlink cachedir css flush + header help htmldir htmlroot + index infile outfile poderrors + podpath podroot quiet recurse + title verbose + |); + unshift @ARGV, split ' ', $Config{pod2html} if $Config{pod2html}; + my $result = GetOptions(\%opts, + 'backlink!', + 'cachedir=s', + 'css=s', + 'flush', + 'help', + 'header!', + 'htmldir=s', + 'htmlroot=s', + 'index!', + 'infile=s', + 'outfile=s', + 'poderrors!', + 'podpath=s', + 'podroot=s', + 'quiet!', + 'recurse!', + 'title=s', + 'verbose!', + ); + usage("-", "invalid parameters") if not $result; + usage("-") if defined $opts{help}; # see if the user asked for help + $opts{help} = ""; # just to make -w shut-up. + return \%opts; +} + +=head2 C<usage()> + +Display customary Pod::Html usage information on STDERR. + +=cut + +sub usage { + my $podfile = shift; + warn "$0: $podfile: @_\n" if @_; + die <<END_OF_USAGE; +Usage: $0 --help --htmldir=<name> --htmlroot=<URL> + --infile=<name> --outfile=<name> + --podpath=<name>:...:<name> --podroot=<name> + --cachedir=<name> --flush --recurse --norecurse + --quiet --noquiet --verbose --noverbose + --index --noindex --backlink --nobacklink + --header --noheader --poderrors --nopoderrors + --css=<URL> --title=<name> + + --[no]backlink - turn =head1 directives into links pointing to the top of + the page (off by default). + --cachedir - directory for the directory cache files. + --css - stylesheet URL + --flush - flushes the directory cache. + --[no]header - produce block header/footer (default is no headers). + --help - prints this message. + --htmldir - directory for resulting HTML files. + --htmlroot - http-server base directory from which all relative paths + in podpath stem (default is /). + --[no]index - generate an index at the top of the resulting html + (default behaviour). + --infile - filename for the pod to convert (input taken from stdin + by default). + --outfile - filename for the resulting html file (output sent to + stdout by default). + --[no]poderrors - include a POD ERRORS section in the output if there were + any POD errors in the input (default behavior). + --podpath - colon-separated list of directories containing library + pods (empty by default). + --podroot - filesystem base directory from which all relative paths + in podpath stem (default is .). + --[no]quiet - suppress some benign warning messages (default is off). + --[no]recurse - recurse on those subdirectories listed in podpath + (default behaviour). + --title - title that will appear in resulting html file. + --[no]verbose - self-explanatory (off by default). + +END_OF_USAGE + +} + +=head2 C<unixify()> + +Ensure that F<Pod::Html>'s internals and tests handle paths consistently +across Unix, Windows and VMS. + +=cut + +sub unixify { + my $full_path = shift; + return '' unless $full_path; + return $full_path if $full_path eq '/'; + + my ($vol, $dirs, $file) = File::Spec->splitpath($full_path); + my @dirs = $dirs eq File::Spec->curdir() + ? (File::Spec::Unix->curdir()) + : File::Spec->splitdir($dirs); + if (defined($vol) && $vol) { + $vol =~ s/:$// if $^O eq 'VMS'; + $vol = uc $vol if $^O eq 'MSWin32'; + + if( $dirs[0] ) { + unshift @dirs, $vol; + } + else { + $dirs[0] = $vol; + } + } + unshift @dirs, '' if File::Spec->file_name_is_absolute($full_path); + return $file unless scalar(@dirs); + $full_path = File::Spec::Unix->catfile(File::Spec::Unix->catdir(@dirs), + $file); + $full_path =~ s|^\/|| if $^O eq 'MSWin32'; # C:/foo works, /C:/foo doesn't + $full_path =~ s/\^\././g if $^O eq 'VMS'; # unescape dots + return $full_path; +} + +=head2 C<relativize_url()> + +Convert an absolute URL to one relative to a base URL. +Assumes both end in a filename. + +=cut + +sub relativize_url { + my ($dest, $source) = @_; + + # Remove each file from its path + my ($dest_volume, $dest_directory, $dest_file) = + File::Spec::Unix->splitpath( $dest ); + $dest = File::Spec::Unix->catpath( $dest_volume, $dest_directory, '' ); + + my ($source_volume, $source_directory, $source_file) = + File::Spec::Unix->splitpath( $source ); + $source = File::Spec::Unix->catpath( $source_volume, $source_directory, '' ); + + my $rel_path = ''; + if ($dest ne '') { + $rel_path = File::Spec::Unix->abs2rel( $dest, $source ); + } + + if ($rel_path ne '' && substr( $rel_path, -1 ) ne '/') { + $rel_path .= "/$dest_file"; + } else { + $rel_path .= "$dest_file"; + } + + return $rel_path; +} + +=head2 C<html_escape()> + +Make text safe for HTML. + +=cut + +sub html_escape { + my $rest = $_[0]; + $rest =~ s/&/&/g; + $rest =~ s/</</g; + $rest =~ s/>/>/g; + $rest =~ s/"/"/g; + $rest =~ s/([[:^print:]])/sprintf("&#x%x;", ord($1))/aeg; + return $rest; +} + +=head2 C<htmlify()> + + htmlify($heading); + +Converts a pod section specification to a suitable section specification +for HTML. Note that we keep spaces and special characters except +C<", ?> (Netscape problem) and the hyphen (writer's problem...). + +=cut + +sub htmlify { + my( $heading) = @_; + return Pod::Simple::XHTML->can("idify")->(undef, $heading, 1); +} + +=head2 C<anchorify()> + + anchorify(@heading); + +Similar to C<htmlify()>, but turns non-alphanumerics into underscores. Note +that C<anchorify()> is not exported by default. + +=cut + +sub anchorify { + my ($anchor) = @_; + $anchor = htmlify($anchor); + $anchor =~ s/\W/_/g; + return $anchor; +} + +=head2 C<trim_leading_whitespace()> + +Remove any level of indentation (spaces or tabs) from each code block +consistently. Adapted from: +https://metacpan.org/source/HAARG/MetaCPAN-Pod-XHTML-0.002001/lib/Pod/Simple/Role/StripVerbatimIndent.pm + +=cut + +sub trim_leading_whitespace { + my ($para) = @_; + + # Start by converting tabs to spaces + @$para = Text::Tabs::expand(@$para); + + # Find the line with the least amount of indent, as that's our "base" + my @indent_levels = (sort(map { $_ =~ /^( *)./mg } @$para)); + my $indent = $indent_levels[0] || ""; + + # Remove the "base" amount of indent from each line + foreach (@$para) { + $_ =~ s/^\Q$indent//mg; + } + + return; +} + +1; + diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Man.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Man.pm index d7c029357a..5ed95bbc90 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Man.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Man.pm @@ -14,36 +14,33 @@ package Pod::Man; -use 5.008; +use 5.010; use strict; use warnings; -use subs qw(makespace); -use vars qw(@ISA %ESCAPES $PREAMBLE $VERSION); - use Carp qw(carp croak); use Pod::Simple (); # Conditionally import Encode and set $HAS_ENCODE if it is available. This is # required to support building as part of Perl core, since podlators is built # before Encode is. -our $HAS_ENCODE; +my $HAS_ENCODE; BEGIN { $HAS_ENCODE = eval { require Encode }; } -@ISA = qw(Pod::Simple); - -$VERSION = '4.14'; - -# Set the debugging level. If someone has inserted a debug function into this -# class already, use that. Otherwise, use any Pod::Simple debug function -# that's defined, and failing that, define a debug level of 10. -BEGIN { - my $parent = defined (&Pod::Simple::DEBUG) ? \&Pod::Simple::DEBUG : undef; - unless (defined &DEBUG) { - *DEBUG = $parent || sub () { 10 }; - } +our @ISA = qw(Pod::Simple); +our $VERSION = '5.01'; + +# Ensure that $Pod::Simple::nbsp and $Pod::Simple::shy are available. Code +# taken from Pod::Simple 3.32, but was only added in 3.30. +my ($NBSP, $SHY); +if ($Pod::Simple::VERSION ge 3.30) { + $NBSP = $Pod::Simple::nbsp; + $SHY = $Pod::Simple::shy; +} else { + $NBSP = chr utf8::unicode_to_native(0xA0); + $SHY = chr utf8::unicode_to_native(0xAD); } # Import the ASCII constant from Pod::Simple. This is true iff we're in an @@ -51,15 +48,12 @@ BEGIN { # generally only false for EBCDIC. BEGIN { *ASCII = \&Pod::Simple::ASCII } -# Pretty-print a data structure. Only used for debugging. -BEGIN { *pretty = \&Pod::Simple::pretty } - # Formatting instructions for various types of blocks. cleanup makes hyphens # hard, adds spaces between consecutive underscores, and escapes backslashes. # convert translates characters into escapes. guesswork means to apply the -# transformations done by the guesswork sub. literal says to protect literal -# quotes from being turned into UTF-8 quotes. By default, all transformations -# are on except literal, but some elements override. +# transformations done by the guesswork sub (if enabled). literal says to +# protect literal quotes from being turned into UTF-8 quotes. By default, all +# transformations are on except literal, but some elements override. # # DEFAULT specifies the default settings. All other elements should list only # those settings that they are overriding. Data indicates =for roff blocks, @@ -75,6 +69,98 @@ my %FORMATTING = ( X => { cleanup => 0, guesswork => 0 }, ); +# Try to map an encoding as understood by Perl Encode to an encoding +# understood by groff's preconv. Encode doesn't care about hyphens or +# capitalization, but preconv does. The key is the canonicalized Encode +# encoding, and the value is something preconv might understand. +# +# FreeBSD mandoc only understands utf-8 and iso-latin-1 as of 2022-09-24. +# groff preconv prefers iso-8859-1, but also understands iso-latin-1, so +# convert ISO-8859-1 to iso-latin-1 for FreeBSD. +my %ENCODINGS = ( + ascii => 'us-ascii', + big5 => 'big5', + big5eten => 'big5', + cp950 => 'big5', + cp1047 => 'cp1047', + euccn => 'gb2312', + eucjp => 'euc-jp', + euckr => 'euc-kr', + gb2312 => 'gb2312', + gb2312raw => 'gb2312', + iso88591 => 'iso-latin-1', + iso88592 => 'iso-8859-2', + iso88595 => 'iso-8859-5', + iso88597 => 'iso-8859-7', + iso88599 => 'iso-8859-9', + iso885913 => 'iso-8859-13', + iso885915 => 'iso-8859-15', + koi8r => 'koi8-r', + latin1 => 'iso-8859-1', + usascii => 'us-ascii', + utf8 => 'utf-8', + utf16 => 'utf-16', + utf16be => 'utf-16be', + utf16le => 'utf-16le', +); + +############################################################################## +# Translation tables +############################################################################## + +# The following table is adapted from Tom Christiansen's pod2man. It is only +# used with roff output. It assumes that the standard preamble has already +# been printed, since that's what defines all of the accent marks. We really +# want to do something better than this when *roff actually supports other +# character sets itself, since these results are pretty poor. +# +# This only works in an ASCII world. What to do in a non-ASCII world is very +# unclear, so we just output what we get and hope for the best. +my %ESCAPES; +@ESCAPES{0xA0 .. 0xFF} = ( + $NBSP, undef, undef, undef, undef, undef, undef, undef, + undef, undef, undef, undef, undef, $SHY, undef, undef, + + undef, undef, undef, undef, undef, undef, undef, undef, + undef, undef, undef, undef, undef, undef, undef, undef, + + "A\\*`", "A\\*'", "A\\*^", "A\\*~", "A\\*:", "A\\*o", "\\*(Ae", "C\\*,", + "E\\*`", "E\\*'", "E\\*^", "E\\*:", "I\\*`", "I\\*'", "I\\*^", "I\\*:", + + "\\*(D-", "N\\*~", "O\\*`", "O\\*'", "O\\*^", "O\\*~", "O\\*:", undef, + "O\\*/", "U\\*`", "U\\*'", "U\\*^", "U\\*:", "Y\\*'", "\\*(Th", "\\*8", + + "a\\*`", "a\\*'", "a\\*^", "a\\*~", "a\\*:", "a\\*o", "\\*(ae", "c\\*,", + "e\\*`", "e\\*'", "e\\*^", "e\\*:", "i\\*`", "i\\*'", "i\\*^", "i\\*:", + + "\\*(d-", "n\\*~", "o\\*`", "o\\*'", "o\\*^", "o\\*~", "o\\*:", undef, + "o\\*/" , "u\\*`", "u\\*'", "u\\*^", "u\\*:", "y\\*'", "\\*(th", "y\\*:", +) if ASCII; + +############################################################################## +# Utility functions +############################################################################## + +# Quote an argument to a macro. +# +# $arg - Intended argument to the macro +# +# Returns: $arg suitably escaped and quoted +sub _quote_macro_argument { + my ($arg) = @_; + if (length($arg) > 0 && $arg !~ m{ [\s\"] }xms) { + return $arg; + } + $arg =~ s{ \" }{""}xmsg; + return qq("$arg"); +} + +# Returns whether the given encoding needs a call to Encode::encode. +sub _needs_encode { + my ($encoding) = @_; + return $encoding ne 'roff' && $encoding ne 'groff'; +} + ############################################################################## # Object initialization ############################################################################## @@ -88,9 +174,6 @@ sub new { my $class = shift; my $self = $class->SUPER::new; - # Tell Pod::Simple not to handle S<> by automatically inserting . - $self->nbsp_for_S (1); - # Tell Pod::Simple to keep whitespace whenever possible. if (my $preserve_whitespace = $self->can ('preserve_whitespace')) { $self->$preserve_whitespace (1); @@ -109,63 +192,84 @@ sub new { # to put them in our object as hash keys and values. This could cause # problems if we ever clash with Pod::Simple's own internal class # variables. - %$self = (%$self, @_); + my %opts = @_; + my @opts = map { ("opt_$_", $opts{$_}) } keys %opts; + %$self = (%$self, @opts); + + # Pod::Simple uses encoding internally, so we need to store it as + # ENCODING. Set the default to UTF-8 if not specified. + # + # Degrade to the old roff encoding if Encode is not available. + # + # Suppress the warning message when PERL_CORE is set, indicating this is + # running as part of the core Perl build. Perl builds podlators (and all + # pure Perl modules) before Encode and other XS modules, so Encode won't + # yet be available. Rely on the Perl core build to generate man pages + # later, after all the modules are available, so that UTF-8 handling will + # be correct. + my %options = @_; + if (defined $self->{opt_encoding}) { + $$self{ENCODING} = $self->{opt_encoding}; + } elsif (ASCII) { + $$self{ENCODING} = 'UTF-8'; + } else { + $$self{ENCODING} = 'groff'; + } + if (_needs_encode($$self{ENCODING}) && !$HAS_ENCODE) { + if (!$ENV{PERL_CORE}) { + carp ('encoding requested but Encode module not available,' + . ' falling back to groff escapes'); + } + $$self{ENCODING} = 'groff'; + } # Send errors to stderr if requested. - if ($$self{stderr} and not $$self{errors}) { - $$self{errors} = 'stderr'; + if ($self->{opt_stderr} and not $self->{opt_errors}) { + $self->{opt_errors} = 'stderr'; } - delete $$self{stderr}; + delete $self->{opt_stderr}; # Validate the errors parameter and act on it. - if (not defined $$self{errors}) { - $$self{errors} = 'pod'; - } - if ($$self{errors} eq 'stderr' || $$self{errors} eq 'die') { + $self->{opt_errors} //= 'pod'; + if ($self->{opt_errors} eq 'stderr' || $self->{opt_errors} eq 'die') { $self->no_errata_section (1); $self->complain_stderr (1); - if ($$self{errors} eq 'die') { - $$self{complain_die} = 1; + if ($self->{opt_errors} eq 'die') { + $self->{complain_die} = 1; } - } elsif ($$self{errors} eq 'pod') { + } elsif ($self->{opt_errors} eq 'pod') { $self->no_errata_section (0); $self->complain_stderr (0); - } elsif ($$self{errors} eq 'none') { + } elsif ($self->{opt_errors} eq 'none') { $self->no_errata_section (1); $self->no_whining (1); } else { - croak (qq(Invalid errors setting: "$$self{errors}")); - } - delete $$self{errors}; - - # Degrade back to non-utf8 if Encode is not available. - # - # Suppress the warning message when PERL_CORE is set, indicating this is - # running as part of the core Perl build. Perl builds podlators (and all - # pure Perl modules) before Encode and other XS modules, so Encode won't - # yet be available. Rely on the Perl core build to generate man pages - # later, after all the modules are available, so that UTF-8 handling will - # be correct. - if ($$self{utf8} and !$HAS_ENCODE) { - if (!$ENV{PERL_CORE}) { - carp ('utf8 mode requested but Encode module not available,' - . ' falling back to non-utf8'); - } - delete $$self{utf8}; + croak (qq(Invalid errors setting: "$self->{opt_errors}")); } + delete $self->{opt_errors}; # Initialize various other internal constants based on our arguments. $self->init_fonts; $self->init_quotes; $self->init_page; - # For right now, default to turning on all of the magic. - $$self{MAGIC_CPP} = 1; - $$self{MAGIC_EMDASH} = 1; - $$self{MAGIC_FUNC} = 1; - $$self{MAGIC_MANREF} = 1; - $$self{MAGIC_SMALLCAPS} = 1; - $$self{MAGIC_VARS} = 1; + # Configure guesswork based on options. + my $guesswork = $self->{opt_guesswork} || q{}; + my %guesswork = map { $_ => 1 } split(m{,}xms, $guesswork); + if (!%guesswork || $guesswork{all}) { + #<<< + $$self{GUESSWORK} = { + functions => 1, + manref => 1, + quoting => 1, + variables => 1, + }; + #>>> + } elsif ($guesswork{none}) { + $$self{GUESSWORK} = {}; + } else { + $$self{GUESSWORK} = {%guesswork}; + } return $self; } @@ -182,29 +286,41 @@ sub init_fonts { # Figure out the fixed-width font. If user-supplied, make sure that they # are the right length. - for (qw/fixed fixedbold fixeditalic fixedbolditalic/) { - my $font = $$self{$_}; - if (defined ($font) && (length ($font) < 1 || length ($font) > 2)) { - croak qq(roff font should be 1 or 2 chars, not "$font"); + for (qw(fixed fixedbold fixeditalic fixedbolditalic)) { + my $font = $self->{"opt_$_"}; + if (defined($font) && (length($font) < 1 || length($font) > 2)) { + croak(qq(roff font should be 1 or 2 chars, not "$font")); } } # Set the default fonts. We can't be sure portably across different # implementations what fixed bold-italic may be called (if it's even # available), so default to just bold. - $$self{fixed} ||= 'CW'; - $$self{fixedbold} ||= 'CB'; - $$self{fixeditalic} ||= 'CI'; - $$self{fixedbolditalic} ||= 'CB'; + #<<< + $self->{opt_fixed} ||= 'CW'; + $self->{opt_fixedbold} ||= 'CB'; + $self->{opt_fixeditalic} ||= 'CI'; + $self->{opt_fixedbolditalic} ||= 'CB'; + #>>> # Set up a table of font escapes. First number is fixed-width, second is # bold, third is italic. - $$self{FONTS} = { '000' => '\fR', '001' => '\fI', - '010' => '\fB', '011' => '\f(BI', - '100' => toescape ($$self{fixed}), - '101' => toescape ($$self{fixeditalic}), - '110' => toescape ($$self{fixedbold}), - '111' => toescape ($$self{fixedbolditalic}) }; + $self->{FONTS} = { + '000' => '\fR', + '001' => '\fI', + '010' => '\fB', + '011' => '\f(BI', + '100' => toescape($self->{opt_fixed}), + '101' => toescape($self->{opt_fixeditalic}), + '110' => toescape($self->{opt_fixedbold}), + '111' => toescape($self->{opt_fixedbolditalic}), + }; + + # Precalculate a regex that matches all fixed-width fonts, which will be + # used later by switchquotes. + my @fixedpat = map { quotemeta($self->{FONTS}{$_}) } qw(100 101 110 111); + my $fixedpat = join('|', @fixedpat); + $self->{FIXEDPAT} = qr{ $fixedpat }xms; } # Initialize the quotes that we'll be using for C<> text. This requires some @@ -215,32 +331,28 @@ sub init_quotes { my ($self) = (@_); # Handle the quotes option first, which sets both quotes at once. - $$self{quotes} ||= '"'; - if ($$self{quotes} eq 'none') { + $self->{opt_quotes} ||= '"'; + if ($self->{opt_quotes} eq 'none') { $$self{LQUOTE} = $$self{RQUOTE} = ''; - } elsif (length ($$self{quotes}) == 1) { - $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes}; - } elsif (length ($$self{quotes}) % 2 == 0) { - my $length = length ($$self{quotes}) / 2; - $$self{LQUOTE} = substr ($$self{quotes}, 0, $length); - $$self{RQUOTE} = substr ($$self{quotes}, $length); + } elsif (length ($self->{opt_quotes}) == 1) { + $$self{LQUOTE} = $$self{RQUOTE} = $self->{opt_quotes}; + } elsif (length ($self->{opt_quotes}) % 2 == 0) { + my $length = length ($self->{opt_quotes}) / 2; + $$self{LQUOTE} = substr ($self->{opt_quotes}, 0, $length); + $$self{RQUOTE} = substr ($self->{opt_quotes}, $length); } else { - croak(qq(Invalid quote specification "$$self{quotes}")) + croak(qq(Invalid quote specification "$self->{opt_quotes}")) } # Now handle the lquote and rquote options. - if (defined $$self{lquote}) { - $$self{LQUOTE} = $$self{lquote} eq 'none' ? q{} : $$self{lquote}; + if (defined($self->{opt_lquote})) { + $self->{opt_lquote} = q{} if $self->{opt_lquote} eq 'none'; + $$self{LQUOTE} = $self->{opt_lquote}; } - if (defined $$self{rquote}) { - $$self{RQUOTE} = $$self{rquote} eq 'none' ? q{} : $$self{rquote}; + if (defined $self->{opt_rquote}) { + $self->{opt_rquote} = q{} if $self->{opt_rquote} eq 'none'; + $$self{RQUOTE} = $self->{opt_rquote}; } - - # Double the first quote; note that this should not be s///g as two double - # quotes is represented in *roff as three double quotes, not four. Weird, - # I know. - $$self{LQUOTE} =~ s/\"/\"\"/; - $$self{RQUOTE} =~ s/\"/\"\"/; } # Initialize the page title information and indentation from our arguments. @@ -254,17 +366,9 @@ sub init_page { # Set the defaults for page titles and indentation if the user didn't # override anything. - $$self{center} = 'User Contributed Perl Documentation' - unless defined $$self{center}; - $$self{release} = 'perl v' . $version - unless defined $$self{release}; - $$self{indent} = 4 - unless defined $$self{indent}; - - # Double quotes in things that will be quoted. - for (qw/center release/) { - $$self{$_} =~ s/\"/\"\"/g if $$self{$_}; - } + $self->{opt_center} //= 'User Contributed Perl Documentation'; + $self->{opt_release} //= 'perl v' . $version; + $self->{opt_indent} //= 4; } ############################################################################## @@ -289,7 +393,6 @@ sub init_page { # according to the current formatting instructions as we do. sub _handle_text { my ($self, $text) = @_; - DEBUG > 3 and print "== $text\n"; my $tag = $$self{PENDING}[-1]; $$tag[2] .= $self->format_text ($$tag[1], $text); } @@ -308,7 +411,6 @@ sub method_for_element { # text and nested elements. Otherwise, if start_element is defined, call it. sub _handle_element_start { my ($self, $element, $attrs) = @_; - DEBUG > 3 and print "++ $element (<", join ('> <', %$attrs), ">)\n"; my $method = $self->method_for_element ($element); # If we have a command handler, we need to accumulate the contents of the @@ -316,7 +418,6 @@ sub _handle_element_start { # <Para> and the formatting codes so that IN_NAME isn't still set for the # first heading after the NAME heading. if ($self->can ("cmd_$method")) { - DEBUG > 2 and print "<$element> starts saving a tag\n"; $$self{IN_NAME} = 0 if ($element ne 'Para' && length ($element) > 1); # How we're going to format embedded text blocks depends on the tag @@ -328,11 +429,8 @@ sub _handle_element_start { %{ $FORMATTING{$element} || {} }, }; push (@{ $$self{PENDING} }, [ $attrs, $formatting, '' ]); - DEBUG > 4 and print "Pending: [", pretty ($$self{PENDING}), "]\n"; } elsif (my $start_method = $self->can ("start_$method")) { $self->$start_method ($attrs, ''); - } else { - DEBUG > 2 and print "No $method start method, skipping\n"; } } @@ -341,16 +439,12 @@ sub _handle_element_start { # an end_ method for the element, call that. sub _handle_element_end { my ($self, $element) = @_; - DEBUG > 3 and print "-- $element\n"; my $method = $self->method_for_element ($element); # If we have a command handler, pull off the pending text and pass it to # the handler along with the saved attribute hash. if (my $cmd_method = $self->can ("cmd_$method")) { - DEBUG > 2 and print "</$element> stops saving a tag\n"; my $tag = pop @{ $$self{PENDING} }; - DEBUG > 4 and print "Popped: [", pretty ($tag), "]\n"; - DEBUG > 4 and print "Pending: [", pretty ($$self{PENDING}), "]\n"; my $text = $self->$cmd_method ($$tag[0], $$tag[2]); if (defined $text) { if (@{ $$self{PENDING} } > 1) { @@ -361,8 +455,6 @@ sub _handle_element_end { } } elsif (my $end_method = $self->can ("end_$method")) { $self->$end_method (); - } else { - DEBUG > 2 and print "No $method end method, skipping\n"; } } @@ -381,31 +473,40 @@ sub format_text { my $literal = $$options{literal}; # Cleanup just tidies up a few things, telling *roff that the hyphens are - # hard, putting a bit of space between consecutive underscores, and - # escaping backslashes. Be careful not to mangle our character - # translations by doing this before processing character translation. + # hard, putting a bit of space between consecutive underscores, escaping + # backslashes, and converting zero-width spaces to zero-width break + # points. if ($cleanup) { $text =~ s/\\/\\e/g; $text =~ s/-/\\-/g; $text =~ s/_(?=_)/_\\|/g; + $text =~ s/\x{200B}/\\:/g; } - # Normally we do character translation, but we won't even do that in - # <Data> blocks or if UTF-8 output is desired. - if ($convert && !$$self{utf8} && ASCII) { - $text =~ s/([^\x00-\x7F])/$ESCAPES{ord ($1)} || "X"/eg; + # Except in <Data> blocks, if groff or roff encoding is requested and + # we're in an ASCII environment, do the encoding. For EBCDIC, we just + # write what we get and hope for the best. Leave non-breaking spaces and + # soft hyphens alone; we'll convert those at the last minute. + if ($convert) { + if (ASCII) { + if ($$self{ENCODING} eq 'groff') { + $text =~ s{ ([^\x00-\x7F\xA0\xAD]) }{ + '\\[u' . sprintf('%04X', ord($1)) . ']' + }xmsge; + } elsif ($$self{ENCODING} eq 'roff') { + $text =~ s/([^\x00-\x7F\xA0\xAD])/$ESCAPES{ord ($1)} || "X"/eg; + } + } } # Ensure that *roff doesn't convert literal quotes to UTF-8 single quotes, - # but don't mess up our accept escapes. + # but don't mess up accent escapes. if ($literal) { $text =~ s/(?<!\\\*)\'/\\*\(Aq/g; $text =~ s/(?<!\\\*)\`/\\\`/g; } - # If guesswork is asked for, do that. This involves more substantial - # formatting based on various heuristics that may only be appropriate for - # particular documents. + # If guesswork is is viable for this block, do that. if ($guesswork) { $text = $self->guesswork ($text); } @@ -420,31 +521,45 @@ sub quote_literal { my $self = shift; local $_ = shift; + # If in NAME section, just return an ASCII quoted string to avoid + # confusing tools like whatis. + if ($$self{IN_NAME}) { + return $self->{LQUOTE} . $_ . $self->{RQUOTE}; + } + # A regex that matches the portion of a variable reference that's the # array or hash index, separated out just because we want to use it in # several places in the following regex. - my $index = '(?: \[.*\] | \{.*\} )?'; - - # If in NAME section, just return an ASCII quoted string to avoid - # confusing tools like whatis. - return qq{"$_"} if $$self{IN_NAME}; + my $index = '(?: \[[^]]+\] | \{[^}]+\} )?'; # Check for things that we don't want to quote, and if we find any of # them, return the string with just a font change and no quoting. + # + # Traditionally, Pod::Man has not quoted Perl variables, functions, + # numbers, or hex constants, but this is not always desirable. Make this + # optional on the quoting guesswork flag. + my $extra = qr{(?!)}xms; # never matches + if ($$self{GUESSWORK}{quoting}) { + $extra = qr{ + \$+ [\#^]? \S $index # special ($^F, $") + | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func + | [\$\@%&*]* [:\'\w]+ + (?: \\-> )? \(\s*[^\s,\)]*\s*\) # 0/1-arg func call + | (?: [+] || \\- )? ( \d[\d.]* | \.\d+ ) + (?: [eE] (?: [+] || \\- )? \d+ )? # a number + | 0x [a-fA-F\d]+ # a hex constant + }xms; + } m{ ^\s* (?: - ( [\'\`\"] ) .* \1 # already quoted - | \\\*\(Aq .* \\\*\(Aq # quoted and escaped - | \\?\` .* ( \' | \\\*\(Aq ) # `quoted' - | \$+ [\#^]? \S $index # special ($^Foo, $") - | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func - | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call - | [-+]? ( \d[\d.]* | \.\d+ ) (?: [eE][-+]?\d+ )? # a number - | 0x [a-fA-F\d]+ # a hex constant + ( [\'\"] ) .* \1 # already quoted + | \\\*\(Aq .* \\\*\(Aq # quoted and escaped + | \\?\` .* ( \' | \\?\` | \\\*\(Aq ) # `quoted' or `quoted` + | $extra ) \s*\z - }xso and return '\f(FS' . $_ . '\f(FE'; + }xms and return '\f(FS' . $_ . '\f(FE'; # If we didn't return, go ahead and quote the text. return '\f(FS\*(C`' . $_ . "\\*(C'\\f(FE"; @@ -453,10 +568,8 @@ sub quote_literal { # Takes a text block to perform guesswork on. Returns the text block with # formatting codes added. This is the code that marks up various Perl # constructs and things commonly used in man pages without requiring the user -# to add any explicit markup, and is applied to all non-literal text. We're -# guaranteed that the text we're applying guesswork to does not contain any -# *roff formatting codes. Note that the inserted font sequences must be -# treated later with mapfonts or textmapfonts. +# to add any explicit markup, and is applied to all non-literal text. Note +# that the inserted font sequences must be treated later with mapfonts. # # This method is very fragile, both in the regular expressions it uses and in # the ordering of those modifications. Care and testing is required when @@ -464,7 +577,6 @@ sub quote_literal { sub guesswork { my $self = shift; local $_ = shift; - DEBUG > 5 and print " Guesswork called on [$_]\n"; # By the time we reach this point, all hyphens will be escaped by adding a # backslash. We want to undo that escaping if they're part of regular @@ -475,9 +587,9 @@ sub guesswork { # Note that this is not user-controllable; we pretty much have to do this # transformation or *roff will mangle the output in unacceptable ways. s{ - ( (?:\G|^|\s) [\(\"]* [a-zA-Z] ) ( \\- )? + ( (?:\G|^|\s|$NBSP) [\(\"]* [a-zA-Z] ) ( \\- )? ( (?: [a-zA-Z\']+ \\-)+ ) - ( [a-zA-Z\']+ ) (?= [\)\".?!,;:]* (?:\s|\Z|\\\ ) ) + ( [a-zA-Z\']+ ) (?= [\)\".?!,;:]* (?:\s|$NBSP|\Z|\\\ ) ) \b } { my ($prefix, $hyphen, $main, $suffix) = ($1, $2, $3, $4); @@ -486,52 +598,17 @@ sub guesswork { $prefix . $hyphen . $main . $suffix; }egx; - # Translate "--" into a real em-dash if it's used like one. This means - # that it's either surrounded by whitespace, it follows a regular word, or - # it occurs between two regular words. - if ($$self{MAGIC_EMDASH}) { - s{ (\s) \\-\\- (\s) } { $1 . '\*(--' . $2 }egx; - s{ (\b[a-zA-Z]+) \\-\\- (\s|\Z|[a-zA-Z]+\b) } { $1 . '\*(--' . $2 }egx; - } - - # Make words in all-caps a little bit smaller; they look better that way. - # However, we don't want to change Perl code (like @ARGV), nor do we want - # to fix the MIME in MIME-Version since it looks weird with the - # full-height V. - # - # We change only a string of all caps (2) either at the beginning of the - # line or following regular punctuation (like quotes) or whitespace (1), - # and followed by either similar punctuation, an em-dash, or the end of - # the line (3). - # - # Allow the text we're changing to small caps to include double quotes, - # commas, newlines, and periods as long as it doesn't otherwise interrupt - # the string of small caps and still fits the criteria. This lets us turn - # entire warranty disclaimers in man page output into small caps. - if ($$self{MAGIC_SMALLCAPS}) { - s{ - ( ^ | [\s\(\"\'\`\[\{<>] | \\[ ] ) # (1) - ( [A-Z] [A-Z] (?: \s? [/A-Z+:\d_\$&] | \\- | \s? [.,\"] )* ) # (2) - (?= [\s>\}\]\(\)\'\".?!,;] | \\*\(-- | \\[ ] | $ ) # (3) - } { - $1 . '\s-1' . $2 . '\s0' - }egx; - } - - # Note that from this point forward, we have to adjust for \s-1 and \s-0 - # strings inserted around things that we've made small-caps if later - # transforms should work on those strings. - # Embolden functions in the form func(), including functions that are in - # all capitals, but don't embolden if there's anything between the parens. + # all capitals, but don't embolden if there's anything inside the parens. # The function must start with an alphabetic character or underscore and # then consist of word characters or colons. - if ($$self{MAGIC_FUNC}) { + if ($$self{GUESSWORK}{functions}) { s{ - ( \b | \\s-1 ) - ( [A-Za-z_] ([:\w] | \\s-?[01])+ \(\) ) + (?<! \\ ) + \b + ( [A-Za-z_] [:\w]+ \(\) ) } { - $1 . '\f(BS' . $2 . '\f(BE' + '\f(BS' . $1 . '\f(BE' }egx; } @@ -542,21 +619,21 @@ sub guesswork { # configuration file man pages), or colons, and n is a single digit, # optionally followed by some number of lowercase letters. Note that this # does not recognize man page references like perl(l) or socket(3SOCKET). - if ($$self{MAGIC_MANREF}) { + if ($$self{GUESSWORK}{manref}) { s{ - ( \b | \\s-1 ) - (?<! \\ ) # rule out \s0(1) - ( [A-Za-z_] (?:[.:\w] | \\- | \\s-?[01])+ ) + \b + (?<! \\ ) # rule out \e0(1) + ( [A-Za-z_] (?:[.:\w] | \\-)+ ) ( \( \d [a-z]* \) ) } { - $1 . '\f(BS' . $2 . '\f(BE\|' . $3 + '\f(BS' . $1 . '\f(BE\|' . $2 }egx; } # Convert simple Perl variable references to a fixed-width font. Be # careful not to convert functions, though; there are too many subtleties # with them to want to perform this transformation. - if ($$self{MAGIC_VARS}) { + if ($$self{GUESSWORK}{variables}) { s{ ( ^ | \s+ ) ( [\$\@%] [\w:]+ ) @@ -566,19 +643,7 @@ sub guesswork { }egx; } - # Fix up double quotes. Unfortunately, we miss this transformation if the - # quoted text contains any code with formatting codes and there's not much - # we can effectively do about that, which makes it somewhat unclear if - # this is really a good idea. - s{ \" ([^\"]+) \" } { '\*(L"' . $1 . '\*(R"' }egx; - - # Make C++ into \*(C+, which is a squinched version. - if ($$self{MAGIC_CPP}) { - s{ \b C\+\+ } {\\*\(C+}gx; - } - # Done. - DEBUG > 5 and print " Guesswork returning [$_]\n"; return $_; } @@ -592,111 +657,106 @@ sub guesswork { # the right start and end codes. # # We add this level of complexity because the old pod2man didn't get code like -# B<someI<thing> else> right; after I<> it switched back to normal text rather -# than bold. We take care of this by using variables that state whether bold, -# italic, or fixed are turned on as a combined pointer to our current font -# sequence, and set each to the number of current nestings of start tags for -# that font. +# B<< someI<thing> else>> right. After I<> it switched back to normal text +# rather than bold. We take care of this by using variables that state +# whether bold, italic, or fixed are turned on as a combined pointer to our +# current font sequence, and set each to the number of current nestings of +# start tags for that font. +# +# The base font must be either \fP or \fR. \fP changes to the previous font, +# but only one previous font is kept. Unfortunately, there is a bug in +# Solaris 2.6 nroff (not present in GNU groff) where the sequence +# \fB\fP\f(CW\fP leaves the font set to B rather than R, presumably because +# \f(CW doesn't actually do a font change. Because of this, we prefer to use +# \fR where possible. +# +# Unfortunately, this isn't possible for arguments to heading macros, since +# there we don't know what the outside level font is. In that case, arrange +# things so that the outside font is always the "previous" font and end with +# \fP instead of \fR. Idea from Zack Weinberg. # -# \fP changes to the previous font, but only one previous font is kept. We -# don't know what the outside level font is; normally it's R, but if we're -# inside a heading it could be something else. So arrange things so that the -# outside font is always the "previous" font and end with \fP instead of \fR. -# Idea from Zack Weinberg. +# This function used to be much simpler outside of macro arguments because it +# went directly from \fB to \f(CW and relied on \f(CW clearing bold since it +# wasn't \f(CB. Unfortunately, while this works for mandoc, this is not how +# groff works; \fBfoo\f(CWbar still prints bar in bold. Therefore, we force +# the font back to the base font before each font change. sub mapfonts { - my ($self, $text) = @_; + my ($self, $text, $base) = @_; + + # The closure used to process each font escape, expected to be called from + # the right-hand side of an s/// expression. my ($fixed, $bold, $italic) = (0, 0, 0); my %magic = (F => \$fixed, B => \$bold, I => \$italic); my $last = '\fR'; - $text =~ s< - \\f\((.)(.) - > < - my $sequence = ''; - my $f; - if ($last ne '\fR') { $sequence = '\fP' } - ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; - $f = $$self{FONTS}{ ($fixed && 1) . ($bold && 1) . ($italic && 1) }; - if ($f eq $last) { - ''; - } else { - if ($f ne '\fR') { $sequence .= $f } - $last = $f; - $sequence; + my $process = sub { + my ($style, $start_stop) = @_; + my $sequence = ($last ne '\fR') ? $base : q{}; + ${ $magic{$style} } += ($start_stop eq 'S') ? 1 : -1; + my $f = $self->{FONTS}{($fixed && 1) . ($bold && 1) . ($italic && 1)}; + return q{} if ($f eq $last); + if ($f ne '\fR') { + $sequence .= $f; } - >gxe; - return $text; -} + $last = $f; + return $sequence; + }; + + # Now, do the actual work. + $text =~ s{ \\f\((.)(.) }{$process->($1, $2)}xmsge; + + # We can do a bit of cleanup by collapsing sequences like \fR\fB\fR\fI + # into just \fI. + $text =~ s{ (?: \\fR )? (?: \\f (.|\(..) \\fR )+ }{\\fR}xms; -# Unfortunately, there is a bug in Solaris 2.6 nroff (not present in GNU -# groff) where the sequence \fB\fP\f(CW\fP leaves the font set to B rather -# than R, presumably because \f(CW doesn't actually do a font change. To work -# around this, use a separate textmapfonts for text blocks where the default -# font is always R and only use the smart mapfonts for headings. -sub textmapfonts { - my ($self, $text) = @_; - my ($fixed, $bold, $italic) = (0, 0, 0); - my %magic = (F => \$fixed, B => \$bold, I => \$italic); - $text =~ s< - \\f\((.)(.) - > < - ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; - $$self{FONTS}{ ($fixed && 1) . ($bold && 1) . ($italic && 1) }; - >gxe; return $text; } # Given a command and a single argument that may or may not contain double -# quotes, handle double-quote formatting for it. If there are no double -# quotes, just return the command followed by the argument in double quotes. -# If there are double quotes, use an if statement to test for nroff, and for -# nroff output the command followed by the argument in double quotes with -# embedded double quotes doubled. For other formatters, remap paired double -# quotes to LQUOTE and RQUOTE. +# quotes and fixed-width text, handle double-quote formatting for it. If +# there is no fixed-width text, just return the command followed by the +# argument with proper quoting. If there is fixed-width text, work around a +# Solaris nroff bug with fixed-width fonts by converting fixed-width to +# regular fonts (nroff sees no difference). sub switchquotes { my ($self, $command, $text, $extra) = @_; - $text =~ s/\\\*\([LR]\"/\"/g; - - # We also have to deal with \*C` and \*C', which are used to add the - # quotes around C<> text, since they may expand to " and if they do this - # confuses the .SH macros and the like no end. Expand them ourselves. - # Also separate troff from nroff if there are any fixed-width fonts in use - # to work around problems with Solaris nroff. - my $c_is_quote = ($$self{LQUOTE} =~ /\"/) || ($$self{RQUOTE} =~ /\"/); - my $fixedpat = join '|', @{ $$self{FONTS} }{'100', '101', '110', '111'}; - $fixedpat =~ s/\\/\\\\/g; - $fixedpat =~ s/\(/\\\(/g; - if ($text =~ m/\"/ || $text =~ m/$fixedpat/) { - $text =~ s/\"/\"\"/g; + + # Separate troff from nroff if there are any fixed-width fonts in use to + # work around problems with Solaris nroff. + if ($text =~ $self->{FIXEDPAT}) { my $nroff = $text; my $troff = $text; - $troff =~ s/\"\"([^\"]*)\"\"/\`\`$1\'\'/g; - if ($c_is_quote and $text =~ m/\\\*\(C[\'\`]/) { - $nroff =~ s/\\\*\(C\`/$$self{LQUOTE}/g; - $nroff =~ s/\\\*\(C\'/$$self{RQUOTE}/g; - $troff =~ s/\\\*\(C[\'\`]//g; - } - $nroff = qq("$nroff") . ($extra ? " $extra" : ''); - $troff = qq("$troff") . ($extra ? " $extra" : ''); # Work around the Solaris nroff bug where \f(CW\fP leaves the font set # to Roman rather than the actual previous font when used in headings. # troff output may still be broken, but at least we can fix nroff by # just switching the font changes to the non-fixed versions. - my $font_end = "(?:\\f[PR]|\Q$$self{FONTS}{100}\E)"; - $nroff =~ s/\Q$$self{FONTS}{100}\E(.*?)\\f([PR])/$1/g; - $nroff =~ s/\Q$$self{FONTS}{101}\E(.*?)$font_end/\\fI$1\\fP/g; - $nroff =~ s/\Q$$self{FONTS}{110}\E(.*?)$font_end/\\fB$1\\fP/g; - $nroff =~ s/\Q$$self{FONTS}{111}\E(.*?)$font_end/\\f\(BI$1\\fP/g; + my $font_end = qr{ (?: \\f[PR] | \Q$self->{FONTS}{100}\E ) }xms; + $nroff =~ s{\Q$self->{FONTS}{100}\E(.*?)\\f([PR])}{$1}xmsg; + $nroff =~ s{\Q$self->{FONTS}{101}\E}{\\fI}xmsg; + $nroff =~ s{\Q$self->{FONTS}{110}\E}{\\fB}xmsg; + $nroff =~ s{\Q$self->{FONTS}{111}\E}{\\f\(BI}xmsg; + + # We have to deal with \*C` and \*C', which are used to add the quotes + # around C<> text, since they may expand to " and if they do this + # confuses the .SH macros and the like no end. Expand them ourselves. + my $c_is_quote = index("$self->{LQUOTE}$self->{RQUOTE}", qq(\")) != -1; + if ($c_is_quote && $text =~ m{ \\[*]\(C[\'\`] }xms) { + $nroff =~ s{ \\[*]\(C\` }{$self->{LQUOTE}}xmsg; + $nroff =~ s{ \\[*]\(C\' }{$self->{RQUOTE}}xmsg; + $troff =~ s{ \\[*]\(C[\'\`] }{}xmsg; + } # Now finally output the command. Bother with .ie only if the nroff # and troff output aren't the same. + $nroff = _quote_macro_argument($nroff) . ($extra ? " $extra" : ''); + $troff = _quote_macro_argument($troff) . ($extra ? " $extra" : ''); if ($nroff ne $troff) { return ".ie n $command $nroff\n.el $command $troff\n"; } else { return "$command $nroff\n"; } } else { - $text = qq("$text") . ($extra ? " $extra" : ''); + $text = _quote_macro_argument($text) . ($extra ? " $extra" : ''); return "$command $text\n"; } } @@ -761,10 +821,22 @@ sub outindex { # Output some text, without any additional changes. sub output { my ($self, @text) = @_; - if ($$self{ENCODE}) { - print { $$self{output_fh} } Encode::encode ('UTF-8', join ('', @text)); + my $text = join('', @text); + $text =~ s{$NBSP}{\\ }g; + $text =~ s{$SHY}{\\%}g; + + if ($$self{ENCODE} && _needs_encode($$self{ENCODING})) { + my $check = sub { + my ($char) = @_; + my $display = '"\x{' . hex($char) . '}"'; + my $error = "$display does not map to $$self{ENCODING}"; + $self->whine ($self->line_count(), $error); + return Encode::encode ($$self{ENCODING}, chr($char)); + }; + my $output = Encode::encode ($$self{ENCODING}, $text, $check); + print { $$self{output_fh} } $output; } else { - print { $$self{output_fh} } @text; + print { $$self{output_fh} } $text; } } @@ -777,21 +849,20 @@ sub output { sub start_document { my ($self, $attrs) = @_; if ($$attrs{contentless} && !$$self{ALWAYS_EMIT_SOMETHING}) { - DEBUG and print "Document is contentless\n"; $$self{CONTENTLESS} = 1; } else { delete $$self{CONTENTLESS}; } - # When UTF-8 output is set, check whether our output file handle already - # has a PerlIO encoding layer set. If it does not, we'll need to encode - # our output before printing it (handled in the output() sub). Wrap the - # check in an eval to handle versions of Perl without PerlIO. + # When an encoding is requested, check whether our output file handle + # already has a PerlIO encoding layer set. If it does not, we'll need to + # encode our output before printing it (handled in the output() sub). + # Wrap the check in an eval to handle versions of Perl without PerlIO. # # PerlIO::get_layers still requires its argument be a glob, so coerce the # file handle to a glob. $$self{ENCODE} = 0; - if ($$self{utf8}) { + if ($$self{ENCODING}) { $$self{ENCODE} = 1; eval { my @options = (output => 1, details => 1); @@ -806,15 +877,15 @@ sub start_document { # document was content-free. if (!$$self{CONTENTLESS}) { my ($name, $section); - if (defined $$self{name}) { - $name = $$self{name}; - $section = $$self{section} || 1; + if (defined $self->{opt_name}) { + $name = $self->{opt_name}; + $section = $self->{opt_section} || 1; } else { ($name, $section) = $self->devise_title; } - my $date = defined($$self{date}) ? $$self{date} : $self->devise_date; + my $date = $self->{opt_date} // $self->devise_date(); $self->preamble ($name, $section, $date) - unless $self->bare_output or DEBUG > 9; + unless $self->bare_output; } # Initialize a few per-document variables. @@ -839,7 +910,6 @@ sub end_document { } return if $self->bare_output; return if ($$self{CONTENTLESS} && !$$self{ALWAYS_EMIT_SOMETHING}); - $self->output (q(.\" [End document]) . "\n") if DEBUG; } # Try to figure out the name and section from the file name and return them as @@ -848,8 +918,8 @@ sub end_document { sub devise_title { my ($self) = @_; my $name = $self->source_filename || ''; - my $section = $$self{section} || 1; - $section = 3 if (!$$self{section} && $name =~ /\.pm\z/i); + my $section = $self->{opt_section} || 1; + $section = 3 if (!$self->{opt_section} && $name =~ /\.pm\z/i); $name =~ s/\.p(od|[lm])\z//i; # If Pod::Parser gave us an IO::File reference as the source file name, @@ -981,34 +1051,53 @@ sub devise_date { # module, but this order is correct for both Solaris and Linux. sub preamble { my ($self, $name, $section, $date) = @_; - my $preamble = $self->preamble_template (!$$self{utf8}); + my $preamble = $self->preamble_template(); - # Build the index line and make sure that it will be syntactically valid. - my $index = "$name $section"; - $index =~ s/\"/\"\"/g; - - # If name or section contain spaces, quote them (section really never - # should, but we may as well be cautious). - for ($name, $section) { - if (/\s/) { - s/\"/\"\"/g; - $_ = '"' . $_ . '"'; + # groff's preconv script will use this line to correctly determine the + # input encoding if the encoding is one of the ones it recognizes. It + # must be the first or second line. + # + # If the output encoding is some version of Unicode, we could also add a + # Unicode Byte Order Mark to the start of the file, but the BOM is now + # deprecated and I am concerned that may break a *roff implementation that + # might otherwise cope with Unicode. Revisit this if someone files a bug + # report about it. + if (_needs_encode($$self{ENCODING})) { + my $normalized = lc($$self{ENCODING}); + $normalized =~ s{-}{}g; + my $coding = $ENCODINGS{$normalized} || lc($$self{ENCODING}); + if ($coding ne 'us-ascii') { + $self->output(qq{.\\\" -*- mode: troff; coding: $coding -*-\n}); } } - # Double quotes in date, since it will be quoted. - $date =~ s/\"/\"\"/g; - - # Substitute into the preamble the configuration options. - $preamble =~ s/\@CFONT\@/$$self{fixed}/; - $preamble =~ s/\@LQUOTE\@/$$self{LQUOTE}/; - $preamble =~ s/\@RQUOTE\@/$$self{RQUOTE}/; - chomp $preamble; + # Substitute into the preamble the configuration options. Because it's + # used as the argument to defining a string, any leading double quote (but + # no other double quotes) in LQUOTE and RQUOTE has to be doubled. + $preamble =~ s{ [@] CFONT [@] }{$self->{opt_fixed}}xms; + my $lquote = $self->{LQUOTE}; + my $rquote = $self->{RQUOTE}; + $lquote =~ s{ \A \" }{""}xms; + $rquote =~ s{ \A \" }{""}xms; + $preamble =~ s{ [@] LQUOTE [@] }{$lquote}xms; + $preamble =~ s{ [@] RQUOTE [@] }{$rquote}xms; + chomp($preamble); # Get the version information. - my $version = $self->version_report; + my $version = $self->version_report(); - # Finally output everything. + # Build the index line and make sure that it will be syntactically valid. + my $index = _quote_macro_argument("$name $section"); + + # Quote the arguments to the .TH macro. (Section should never require + # this, but we may as well be cautious.) + $name = _quote_macro_argument($name); + $section = _quote_macro_argument($section); + $date = _quote_macro_argument($date); + my $center = _quote_macro_argument($self->{opt_center}); + my $release = _quote_macro_argument($self->{opt_release}); + + # Output the majority of the preamble. $self->output (<<"----END OF HEADER----"); .\\" Automatically generated by $version .\\" @@ -1017,14 +1106,19 @@ sub preamble { $preamble .\\" ======================================================================== .\\" -.IX Title "$index" -.TH $name $section "$date" "$$self{release}" "$$self{center}" +.IX Title $index +.TH $name $section $date $release $center .\\" For nroff, turn off justification. Always turn off hyphenation; it makes .\\" way too many mistakes in technical documents. .if n .ad l .nh ----END OF HEADER---- - $self->output (".\\\" [End of preamble]\n") if DEBUG; + + # If the language was specified, output the language configuration. + if ($self->{opt_language}) { + $self->output(".mso $self->{opt_language}.tmac\n"); + $self->output(".hla $self->{opt_language}\n"); + } } ############################################################################## @@ -1049,11 +1143,6 @@ sub cmd_para { $$self{SHIFTWAIT} = 0; } - # Add the line number for debugging, but not in the NAME section just in - # case the comment would confuse apropos. - $self->output (".\\\" [At source line $line]\n") - if defined ($line) && DEBUG && !$$self{IN_NAME}; - # Force exactly one newline at the end and strip unwanted trailing # whitespace at the end, but leave "\ " backslashed space from an S< > at # the end of a line. Reverse the text first, to avoid having to scan the @@ -1063,8 +1152,8 @@ sub cmd_para { $text = reverse $text; # Output the paragraph. - $self->output ($self->protect ($self->textmapfonts ($text))); - $self->outindex; + $self->output($self->protect($self->mapfonts($text, '\fR'))); + $self->outindex(); $$self{NEEDSPACE} = 1; return ''; } @@ -1076,45 +1165,44 @@ sub cmd_verbatim { my ($self, $attrs, $text) = @_; # Ignore an empty verbatim paragraph. - return unless $text =~ /\S/; + return if $text !~ m{ \S }xms; # Force exactly one newline at the end and strip unwanted trailing - # whitespace at the end. Reverse the text first, to avoid having to scan - # the entire paragraph. - $text = reverse $text; - $text =~ s/\A\s*/\n/; - $text = reverse $text; + # whitespace at the end. + $text =~ s{ \s* \z }{\n}xms; # Get a count of the number of lines before the first blank line, which # we'll pass to .Vb as its parameter. This tells *roff to keep that many # lines together. We don't want to tell *roff to keep huge blocks # together. - my @lines = split (/\n/, $text); + my @lines = split (m{ \n }xms, $text); my $unbroken = 0; - for (@lines) { - last if /^\s*$/; + for my $line (@lines) { + last if $line =~ m{ \A \s* \z }xms; $unbroken++; } - $unbroken = 10 if ($unbroken > 12 && !$$self{MAGIC_VNOPAGEBREAK_LIMIT}); + if ($unbroken > 12) { + $unbroken = 10; + } - # Prepend a null token to each line. - $text =~ s/^/\\&/gm; + # Prepend a null token to each line to preserve indentation. + $text =~ s{ ^ }{\\&}xmsg; # Output the results. - $self->makespace; - $self->output (".Vb $unbroken\n$text.Ve\n"); + $self->makespace(); + $self->output(".Vb $unbroken\n$text.Ve\n"); $$self{NEEDSPACE} = 1; - return ''; + return q{}; } # Handle literal text (produced by =for and similar constructs). Just output # it with the minimum of changes. sub cmd_data { my ($self, $attrs, $text) = @_; - $text =~ s/^\n+//; - $text =~ s/\n{0,2}$/\n/; - $self->output ($text); - return ''; + $text =~ s{ \A \n+ }{}xms; + $text =~ s{ \n{0,2} \z }{\n}xms; + $self->output($text); + return q{}; } ############################################################################## @@ -1136,9 +1224,6 @@ sub heading_common { $self->output (".PD\n"); } - # Output the current source line. - $self->output ( ".\\\" [At source line $line]\n" ) - if defined ($line) && DEBUG; return $text; } @@ -1151,7 +1236,7 @@ sub cmd_head1 { $text =~ s/\\s-?\d//g; $text = $self->heading_common ($text, $$attrs{start_line}); my $isname = ($text eq 'NAME' || $text =~ /\(NAME\)/); - $self->output ($self->switchquotes ('.SH', $self->mapfonts ($text))); + $self->output($self->switchquotes('.SH', $self->mapfonts($text, '\fP'))); $self->outindex ('Header', $text) unless $isname; $$self{NEEDSPACE} = 0; $$self{IN_NAME} = $isname; @@ -1162,7 +1247,7 @@ sub cmd_head1 { sub cmd_head2 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); - $self->output ($self->switchquotes ('.SS', $self->mapfonts ($text))); + $self->output($self->switchquotes('.SS', $self->mapfonts($text, '\fP'))); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 0; return ''; @@ -1174,7 +1259,7 @@ sub cmd_head3 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); $self->makespace; - $self->output ($self->textmapfonts ('\f(IS' . $text . '\f(IE') . "\n"); + $self->output($self->mapfonts('\f(IS' . $text . '\f(IE', '\fR') . "\n"); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 1; return ''; @@ -1186,7 +1271,7 @@ sub cmd_head4 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); $self->makespace; - $self->output ($self->textmapfonts ($text) . "\n"); + $self->output($self->mapfonts($text, '\fR') . "\n"); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 1; return ''; @@ -1203,6 +1288,13 @@ sub cmd_i { return $_[0]->{IN_NAME} ? $_[2] : '\f(IS' . $_[2] . '\f(IE' } sub cmd_f { return $_[0]->{IN_NAME} ? $_[2] : '\f(IS' . $_[2] . '\f(IE' } sub cmd_c { return $_[0]->quote_literal ($_[2]) } +# Convert all internal whitespace to $NBSP. +sub cmd_s { + my ($self, $attrs, $text) = @_; + $text =~ s{ \s }{$NBSP}xmsg; + return $text; +} + # Index entries are just added to the pending entries. sub cmd_x { my ($self, $attrs, $text) = @_; @@ -1224,7 +1316,7 @@ sub cmd_l { } if (not defined ($to) or $to eq $text) { return "<$text>"; - } elsif ($$self{nourls}) { + } elsif ($self->{opt_nourls}) { return $text; } else { return "$text <$$attrs{to}>"; @@ -1245,12 +1337,10 @@ sub over_common_start { my ($self, $type, $attrs) = @_; my $line = $$attrs{start_line}; my $indent = $$attrs{indent}; - DEBUG > 3 and print " Starting =over $type (line $line, indent ", - ($indent || '?'), "\n"; # Find the indentation level. unless (defined ($indent) && $indent =~ /^[-+]?\d{1,4}\s*$/) { - $indent = $$self{indent}; + $indent = $self->{opt_indent}; } # If we've gotten multiple indentations in a row, we need to emit the @@ -1279,7 +1369,6 @@ sub over_common_start { # .RE and then a new .RS to unconfuse *roff. sub over_common_end { my ($self) = @_; - DEBUG > 3 and print " Ending =over\n"; $$self{INDENT} = pop @{ $$self{INDENTS} }; pop @{ $$self{ITEMTYPES} }; @@ -1318,7 +1407,6 @@ sub end_over_block { $_[0]->over_common_end } sub item_common { my ($self, $type, $attrs, $text) = @_; my $line = $$attrs{start_line}; - DEBUG > 3 and print " $type item (line $line): $text\n"; # Clean up the text. We want to end up with two variables, one ($text) # which contains any body text after taking out the item portion, and @@ -1350,8 +1438,8 @@ sub item_common { $self->output (".PD 0\n") if ($$self{ITEMS} == 1); # Now, output the item tag itself. - $item = $self->textmapfonts ($item); - $self->output ($self->switchquotes ('.IP', $item, $$self{INDENT})); + $item = $self->mapfonts($item, '\fR'); + $self->output($self->switchquotes('.IP', $item, $$self{INDENT})); $$self{NEEDSPACE} = 0; $$self{ITEMS}++; $$self{SHIFTWAIT} = 0; @@ -1360,7 +1448,7 @@ sub item_common { if ($text) { $text =~ s/\s*$/\n/; $self->makespace; - $self->output ($self->protect ($self->textmapfonts ($text))); + $self->output($self->protect($self->mapfonts($text, '\fR'))); $$self{NEEDSPACE} = 1; } $self->outindex ($index ? ('Item', $index) : ()); @@ -1448,48 +1536,15 @@ sub parse_string_document { } ############################################################################## -# Translation tables -############################################################################## - -# The following table is adapted from Tom Christiansen's pod2man. It assumes -# that the standard preamble has already been printed, since that's what -# defines all of the accent marks. We really want to do something better than -# this when *roff actually supports other character sets itself, since these -# results are pretty poor. -# -# This only works in an ASCII world. What to do in a non-ASCII world is very -# unclear -- hopefully we can assume UTF-8 and just leave well enough alone. -@ESCAPES{0xA0 .. 0xFF} = ( - "\\ ", undef, undef, undef, undef, undef, undef, undef, - undef, undef, undef, undef, undef, "\\%", undef, undef, - - undef, undef, undef, undef, undef, undef, undef, undef, - undef, undef, undef, undef, undef, undef, undef, undef, - - "A\\*`", "A\\*'", "A\\*^", "A\\*~", "A\\*:", "A\\*o", "\\*(Ae", "C\\*,", - "E\\*`", "E\\*'", "E\\*^", "E\\*:", "I\\*`", "I\\*'", "I\\*^", "I\\*:", - - "\\*(D-", "N\\*~", "O\\*`", "O\\*'", "O\\*^", "O\\*~", "O\\*:", undef, - "O\\*/", "U\\*`", "U\\*'", "U\\*^", "U\\*:", "Y\\*'", "\\*(Th", "\\*8", - - "a\\*`", "a\\*'", "a\\*^", "a\\*~", "a\\*:", "a\\*o", "\\*(ae", "c\\*,", - "e\\*`", "e\\*'", "e\\*^", "e\\*:", "i\\*`", "i\\*'", "i\\*^", "i\\*:", - - "\\*(d-", "n\\*~", "o\\*`", "o\\*'", "o\\*^", "o\\*~", "o\\*:", undef, - "o\\*/" , "u\\*`", "u\\*'", "u\\*^", "u\\*:", "y\\*'", "\\*(th", "y\\*:", -) if ASCII; - -############################################################################## # Premable ############################################################################## -# The following is the static preamble which starts all *roff output we -# generate. Most is static except for the font to use as a fixed-width font, -# which is designed by @CFONT@, and the left and right quotes to use for C<> -# text, designated by @LQOUTE@ and @RQUOTE@. However, the second part, which -# defines the accent marks, is only used if $escapes is set to true. +# The preamble which starts all *roff output we generate. Most is static +# except for the font to use as a fixed-width font (designed by @CFONT@), and +# the left and right quotes to use for C<> text (designated by @LQOUTE@ and +# @RQUOTE@). Accent marks are only defined if the output encoding is roff. sub preamble_template { - my ($self, $accents) = @_; + my ($self) = @_; my $preamble = <<'----END OF PREAMBLE----'; .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v @@ -1504,29 +1559,12 @@ sub preamble_template { .ft R .fi .. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" . ds C` @LQUOTE@ . ds C' @RQUOTE@ 'br\} .el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' . ds C` . ds C' 'br\} @@ -1560,7 +1598,7 @@ sub preamble_template { ----END OF PREAMBLE---- #'# for cperl-mode - if ($accents) { + if ($$self{ENCODING} eq 'roff') { $preamble .= <<'----END OF PREAMBLE----' .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). @@ -1590,7 +1628,7 @@ sub preamble_template { . ds / .\} .if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h'|\\n:u' . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' @@ -1637,10 +1675,13 @@ sub preamble_template { 1; __END__ +=encoding UTF-8 + =for stopwords en em ALLCAPS teeny fixedbold fixeditalic fixedbolditalic stderr utf8 UTF-8 Allbery Sean Burke Ossanna Solaris formatters troff uppercased Christiansen -nourls parsers Kernighan lquote rquote +nourls parsers Kernighan lquote rquote unrepresentable mandoc NetBSD PostScript +SMP macOS EBCDIC fallbacks manref reflowed reflowing FH overridable =head1 NAME @@ -1666,100 +1707,197 @@ using L<nroff(1)>, normally via L<man(1)>, or printing using L<troff(1)>. It is conventionally invoked using the driver script B<pod2man>, but it can also be used directly. -As a derived class from Pod::Simple, Pod::Man supports the same methods and -interfaces. See L<Pod::Simple> for all the details. - -new() can take options, in the form of key/value pairs that control the -behavior of the parser. See below for details. - -If no options are given, Pod::Man uses the name of the input file with any -trailing C<.pod>, C<.pm>, or C<.pl> stripped as the man page title, to -section 1 unless the file ended in C<.pm> in which case it defaults to -section 3, to a centered title of "User Contributed Perl Documentation", to -a centered footer of the Perl version it is run with, and to a left-hand -footer of the modification date of its input (or the current date if given -C<STDIN> for input). - -Pod::Man assumes that your *roff formatters have a fixed-width font named -C<CW>. If yours is called something else (like C<CR>), use the C<fixed> -option to specify it. This generally only matters for troff output for -printing. Similarly, you can set the fonts used for bold, italic, and -bold italic fixed-width output. - -Besides the obvious pod conversions, Pod::Man also takes care of -formatting func(), func(3), and simple variable references like $foo or -@bar so you don't have to use code escapes for them; complex expressions -like C<$fred{'stuff'}> will still need to be escaped, though. It also -translates dashes that aren't used as hyphens into en dashes, makes long -dashes--like this--into proper em dashes, fixes "paired quotes," makes C++ -look right, puts a little space between double underscores, makes ALLCAPS -a teeny bit smaller in B<troff>, and escapes stuff that *roff treats as -special so that you don't have to. - -The recognized options to new() are as follows. All options take a single -argument. +By default (on non-EBCDIC systems), Pod::Man outputs UTF-8. Its output should +work with the B<man> program on systems that use B<groff> (most Linux +distributions) or B<mandoc> (most BSD variants), but may result in mangled +output on older UNIX systems. To choose a different, possibly more +backward-compatible output mangling on such systems, set the C<encoding> +option to C<roff> (the default in earlier Pod::Man versions). See the +C<encoding> option and L</ENCODING> for more details. + +See L</COMPATIBILTY> for the versions of Pod::Man with significant +backward-incompatible changes (other than constructor options, whose versions +are documented below), and the versions of Perl that included them. + +=head1 CLASS METHODS + +=over 4 + +=item new(ARGS) + +Create a new Pod::Man object. ARGS should be a list of key/value pairs, where +the keys are chosen from the following. Each option is annotated with the +version of Pod::Man in which that option was added with its current meaning. =over 4 =item center -Sets the centered page header for the C<.TH> macro. The default, if this -option is not specified, is "User Contributed Perl Documentation". +[1.00] Sets the centered page header for the C<.TH> macro. The default, if +this option is not specified, is C<User Contributed Perl Documentation>. =item date -Sets the left-hand footer for the C<.TH> macro. If this option is not set, -the contents of the environment variable POD_MAN_DATE, if set, will be used. -Failing that, the value of SOURCE_DATE_EPOCH, the modification date of the -input file, or the current time if stat() can't find that file (which will be -the case if the input is from C<STDIN>) will be used. If obtained from the -file modification date or the current time, the date will be formatted as -C<YYYY-MM-DD> and will be based on UTC (so that the output will be -reproducible regardless of local time zone). +[4.00] Sets the left-hand footer for the C<.TH> macro. If this option is not +set, the contents of the environment variable POD_MAN_DATE, if set, will be +used. Failing that, the value of SOURCE_DATE_EPOCH, the modification date of +the input file, or the current time if stat() can't find that file (which will +be the case if the input is from C<STDIN>) will be used. If taken from any +source other than POD_MAN_DATE (which is used verbatim), the date will be +formatted as C<YYYY-MM-DD> and will be based on UTC (so that the output will +be reproducible regardless of local time zone). + +=item encoding + +[5.00] Specifies the encoding of the output. The value must be an encoding +recognized by the L<Encode> module (see L<Encode::Supported>), or the special +values C<roff> or C<groff>. The default on non-EBCDIC systems is UTF-8. + +If the output contains characters that cannot be represented in this encoding, +that is an error that will be reported as configured by the C<errors> option. +If error handling is other than C<die>, the unrepresentable character will be +replaced with the Encode substitution character (normally C<?>). + +If the C<encoding> option is set to the special value C<groff> (the default on +EBCDIC systems), or if the Encode module is not available and the encoding is +set to anything other than C<roff>, Pod::Man will translate all non-ASCII +characters to C<\[uNNNN]> Unicode escapes. These are not traditionally part +of the *roff language, but are supported by B<groff> and B<mandoc> and thus by +the majority of manual page processors in use today. + +If the C<encoding> option is set to the special value C<roff>, Pod::Man will +do its historic transformation of (some) ISO 8859-1 characters into *roff +escapes that may be adequate in troff and may be readable (if ugly) in nroff. +This was the default behavior of versions of Pod::Man before 5.00. With this +encoding, all other non-ASCII characters will be replaced with C<X>. It may +be required for very old troff and nroff implementations that do not support +UTF-8, but its representation of any non-ASCII character is very poor and +often specific to European languages. + +If the output file handle has a PerlIO encoding layer set, setting C<encoding> +to anything other than C<groff> or C<roff> will be ignored and no encoding +will be done by Pod::Man. It will instead rely on the encoding layer to make +whatever output encoding transformations are desired. + +WARNING: The input encoding of the POD source is independent from the output +encoding, and setting this option does not affect the interpretation of the +POD input. Unless your POD source is US-ASCII, its encoding should be +declared with the C<=encoding> command in the source. If this is not done, +Pod::Simple will will attempt to guess the encoding and may be successful if +it's Latin-1 or UTF-8, but it will produce warnings. See L<perlpod(1)> for +more information. =item errors -How to report errors. C<die> says to throw an exception on any POD -formatting error. C<stderr> says to report errors on standard error, but -not to throw an exception. C<pod> says to include a POD ERRORS section -in the resulting documentation summarizing the errors. C<none> ignores -POD errors entirely, as much as possible. +[2.27] How to report errors. C<die> says to throw an exception on any POD +formatting error. C<stderr> says to report errors on standard error, but not +to throw an exception. C<pod> says to include a POD ERRORS section in the +resulting documentation summarizing the errors. C<none> ignores POD errors +entirely, as much as possible. The default is C<pod>. =item fixed -The fixed-width font to use for verbatim text and code. Defaults to -C<CW>. Some systems may want C<CR> instead. Only matters for B<troff> -output. +[1.00] The fixed-width font to use for verbatim text and code. Defaults to +C<CW>. Some systems prefer C<CR> instead. Only matters for B<troff> output. =item fixedbold -Bold version of the fixed-width font. Defaults to C<CB>. Only matters +[1.00] Bold version of the fixed-width font. Defaults to C<CB>. Only matters for B<troff> output. =item fixeditalic -Italic version of the fixed-width font (actually, something of a misnomer, -since most fixed-width fonts only have an oblique version, not an italic -version). Defaults to C<CI>. Only matters for B<troff> output. +[1.00] Italic version of the fixed-width font (something of a misnomer, since +most fixed-width fonts only have an oblique version, not an italic version). +Defaults to C<CI>. Only matters for B<troff> output. =item fixedbolditalic -Bold italic (probably actually oblique) version of the fixed-width font. -Pod::Man doesn't assume you have this, and defaults to C<CB>. Some -systems (such as Solaris) have this font available as C<CX>. Only matters -for B<troff> output. +[1.00] Bold italic (in theory, probably oblique in practice) version of the +fixed-width font. Pod::Man doesn't assume you have this, and defaults to +C<CB>. Some systems (such as Solaris) have this font available as C<CX>. +Only matters for B<troff> output. + +=item guesswork + +[5.00] By default, Pod::Man applies some default formatting rules based on +guesswork and regular expressions that are intended to make writing Perl +documentation easier and require less explicit markup. These rules may not +always be appropriate, particularly for documentation that isn't about Perl. +This option allows turning all or some of it off. + +The special value C<all> enables all guesswork. This is also the default for +backward compatibility reasons. The special value C<none> disables all +guesswork. Otherwise, the value of this option should be a comma-separated +list of one or more of the following keywords: + +=over 4 + +=item functions + +Convert function references like C<foo()> to bold even if they have no markup. +The function name accepts valid Perl characters for function names (including +C<:>), and the trailing parentheses must be present and empty. + +=item manref + +Make the first part (before the parentheses) of manual page references like +C<foo(1)> bold even if they have no markup. The section must be a single +number optionally followed by lowercase letters. + +=item quoting + +If no guesswork is enabled, any text enclosed in CZ<><> is surrounded by +double quotes in nroff (terminal) output unless the contents are already +quoted. When this guesswork is enabled, quote marks will also be suppressed +for Perl variables, function names, function calls, numbers, and hex +constants. + +=item variables + +Convert Perl variable names to a fixed-width font even if they have no markup. +This transformation will only be apparent in troff output, or some other +output format (unlike nroff terminal output) that supports fixed-width fonts. + +=back + +Any unknown guesswork name is silently ignored (for potential future +compatibility), so be careful about spelling. + +=item language + +[5.00] Add commands telling B<groff> that the input file is in the given +language. The value of this setting must be a language abbreviation for which +B<groff> provides supplemental configuration, such as C<ja> (for Japanese) or +C<zh> (for Chinese). + +Specifically, this adds: + + .mso <language>.tmac + .hla <language> + +to the start of the file, which configure correct line breaking for the +specified language. Without these commands, groff may not know how to add +proper line breaks for Chinese and Japanese text if the manual page is +installed into the normal manual page directory, such as F</usr/share/man>. + +On many systems, this will be done automatically if the manual page is +installed into a language-specific manual page directory, such as +F</usr/share/man/zh_CN>. In that case, this option is not required. + +Unfortunately, the commands added with this option are specific to B<groff> +and will not work with other B<troff> and B<nroff> implementations. =item lquote =item rquote -Sets the quote marks used to surround CE<lt>> text. C<lquote> sets the -left quote mark and C<rquote> sets the right quote mark. Either may also -be set to the special value C<none>, in which case no quote mark is added -on that side of CE<lt>> text (but the font is still changed for troff -output). +[4.08] Sets the quote marks used to surround CE<lt>> text. C<lquote> sets the +left quote mark and C<rquote> sets the right quote mark. Either may also be +set to the special value C<none>, in which case no quote mark is added on that +side of CE<lt>> text (but the font is still changed for troff output). Also see the C<quotes> option, which can be used to set both quotes at once. If both C<quotes> and one of the other options is set, C<lquote> or C<rquote> @@ -1767,21 +1905,21 @@ overrides C<quotes>. =item name -Set the name of the manual page for the C<.TH> macro. Without this -option, the manual name is set to the uppercased base name of the file -being converted unless the manual section is 3, in which case the path is -parsed to see if it is a Perl module path. If it is, a path like -C<.../lib/Pod/Man.pm> is converted into a name like C<Pod::Man>. This -option, if given, overrides any automatic determination of the name. +[4.08] Set the name of the manual page for the C<.TH> macro. Without this +option, the manual name is set to the uppercased base name of the file being +converted unless the manual section is 3, in which case the path is parsed to +see if it is a Perl module path. If it is, a path like C<.../lib/Pod/Man.pm> +is converted into a name like C<Pod::Man>. This option, if given, overrides +any automatic determination of the name. If generating a manual page from standard input, the name will be set to -C<STDIN> if this option is not provided. Providing this option is strongly -recommended to set a meaningful manual page name. +C<STDIN> if this option is not provided. In this case, providing this option +is strongly recommended to set a meaningful manual page name. =item nourls -Normally, LZ<><> formatting codes with a URL but anchor text are formatted -to show both the anchor text and the URL. In other words: +[2.27] Normally, LZ<><> formatting codes with a URL but anchor text are +formatted to show both the anchor text and the URL. In other words: L<foo|http://example.com/> @@ -1796,10 +1934,10 @@ important. =item quotes -Sets the quote marks used to surround CE<lt>> text. If the value is a -single character, it is used as both the left and right quote. Otherwise, -it is split in half, and the first half of the string is used as the left -quote and the second is used as the right quote. +[4.00] Sets the quote marks used to surround CE<lt>> text. If the value is a +single character, it is used as both the left and right quote. Otherwise, it +is split in half, and the first half of the string is used as the left quote +and the second is used as the right quote. This may also be set to the special value C<none>, in which case no quote marks are added around CE<lt>> text (but the font is still changed for troff @@ -1811,82 +1949,258 @@ options is set, C<lquote> or C<rquote> overrides C<quotes>. =item release -Set the centered footer for the C<.TH> macro. By default, this is set to -the version of Perl you run Pod::Man under. Setting this to the empty -string will cause some *roff implementations to use the system default -value. +[1.00] Set the centered footer for the C<.TH> macro. By default, this is set +to the version of Perl you run Pod::Man under. Setting this to the empty +string will cause some *roff implementations to use the system default value. -Note that some system C<an> macro sets assume that the centered footer -will be a modification date and will prepend something like "Last -modified: ". If this is the case for your target system, you may want to -set C<release> to the last modified date and C<date> to the version -number. +Note that some system C<an> macro sets assume that the centered footer will be +a modification date and will prepend something like C<Last modified: >. If +this is the case for your target system, you may want to set C<release> to the +last modified date and C<date> to the version number. =item section -Set the section for the C<.TH> macro. The standard section numbering -convention is to use 1 for user commands, 2 for system calls, 3 for -functions, 4 for devices, 5 for file formats, 6 for games, 7 for -miscellaneous information, and 8 for administrator commands. There is a lot -of variation here, however; some systems (like Solaris) use 4 for file -formats, 5 for miscellaneous information, and 7 for devices. Still others -use 1m instead of 8, or some mix of both. About the only section numbers -that are reliably consistent are 1, 2, and 3. +[1.00] Set the section for the C<.TH> macro. The standard section numbering +convention is to use 1 for user commands, 2 for system calls, 3 for functions, +4 for devices, 5 for file formats, 6 for games, 7 for miscellaneous +information, and 8 for administrator commands. There is a lot of variation +here, however; some systems (like Solaris) use 4 for file formats, 5 for +miscellaneous information, and 7 for devices. Still others use 1m instead of +8, or some mix of both. About the only section numbers that are reliably +consistent are 1, 2, and 3. By default, section 1 will be used unless the file ends in C<.pm> in which case section 3 will be selected. =item stderr -Send error messages about invalid POD to standard error instead of -appending a POD ERRORS section to the generated *roff output. This is -equivalent to setting C<errors> to C<stderr> if C<errors> is not already -set. It is supported for backward compatibility. +[2.19] If set to a true value, send error messages about invalid POD to +standard error instead of appending a POD ERRORS section to the generated +*roff output. This is equivalent to setting C<errors> to C<stderr> if +C<errors> is not already set. + +This option is for backward compatibility with Pod::Man versions that did not +support C<errors>. Normally, the C<errors> option should be used instead. =item utf8 -By default, Pod::Man produces the most conservative possible *roff output -to try to ensure that it will work with as many different *roff -implementations as possible. Many *roff implementations cannot handle -non-ASCII characters, so this means all non-ASCII characters are converted -either to a *roff escape sequence that tries to create a properly accented -character (at least for troff output) or to C<X>. - -If this option is set, Pod::Man will instead output UTF-8. If your *roff -implementation can handle it, this is the best output format to use and -avoids corruption of documents containing non-ASCII characters. However, -be warned that *roff source with literal UTF-8 characters is not supported -by many implementations and may even result in segfaults and other bad -behavior. - -Be aware that, when using this option, the input encoding of your POD -source should be properly declared unless it's US-ASCII. Pod::Simple will -attempt to guess the encoding and may be successful if it's Latin-1 or -UTF-8, but it will produce warnings. Use the C<=encoding> command to -declare the encoding. See L<perlpod(1)> for more information. +[2.21] This option used to set the output encoding to UTF-8. Since this is +now the default, it is ignored and does nothing. + +=back =back -The standard Pod::Simple method parse_file() takes one argument naming the -POD file to read from. By default, the output is sent to C<STDOUT>, but -this can be changed with the output_fh() method. +=head1 INSTANCE METHODS + +As a derived class from Pod::Simple, Pod::Man supports the same methods and +interfaces. See L<Pod::Simple> for all the details. This section summarizes +the most-frequently-used methods and the ones added by Pod::Man. + +=over 4 + +=item output_fh(FH) + +Direct the output from parse_file(), parse_lines(), or parse_string_document() +to the file handle FH instead of C<STDOUT>. + +=item output_string(REF) + +Direct the output from parse_file(), parse_lines(), or parse_string_document() +to the scalar variable pointed to by REF, rather than C<STDOUT>. For example: + + my $man = Pod::Man->new(); + my $output; + $man->output_string(\$output); + $man->parse_file('/some/input/file'); -The standard Pod::Simple method parse_from_file() takes up to two -arguments, the first being the input file to read POD from and the second -being the file to write the formatted output to. +Be aware that the output in that variable will already be encoded in UTF-8. -You can also call parse_lines() to parse an array of lines or -parse_string_document() to parse a document already in memory. As with -parse_file(), parse_lines() and parse_string_document() default to sending -their output to C<STDOUT> unless changed with the output_fh() method. Be -aware that parse_lines() and parse_string_document() both expect raw bytes, -not decoded characters. +=item parse_file(PATH) -To put the output from any parse method into a string instead of a file -handle, call the output_string() method instead of output_fh(). +Read the POD source from PATH and format it. By default, the output is sent +to C<STDOUT>, but this can be changed with the output_fh() or output_string() +methods. -See L<Pod::Simple> for more specific details on the methods available to -all derived parsers. +=item parse_from_file(INPUT, OUTPUT) + +=item parse_from_filehandle(FH, OUTPUT) + +Read the POD source from INPUT, format it, and output the results to OUTPUT. + +parse_from_filehandle() is provided for backward compatibility with older +versions of Pod::Man. parse_from_file() should be used instead. + +=item parse_lines(LINES[, ...[, undef]]) + +Parse the provided lines as POD source, writing the output to either C<STDOUT> +or the file handle set with the output_fh() or output_string() methods. This +method can be called repeatedly to provide more input lines. An explicit +C<undef> should be passed to indicate the end of input. + +This method expects raw bytes, not decoded characters. + +=item parse_string_document(INPUT) + +Parse the provided scalar variable as POD source, writing the output to either +C<STDOUT> or the file handle set with the output_fh() or output_string() +methods. + +This method expects raw bytes, not decoded characters. + +=back + +=head1 ENCODING + +As of Pod::Man 5.00, the default output encoding for Pod::Man is UTF-8. This +should work correctly on any modern system that uses either B<groff> (most +Linux distributions) or B<mandoc> (Alpine Linux and most BSD variants, +including macOS). + +The user will probably have to use a UTF-8 locale to see correct output. This +may be done by default; if not, set the LANG or LC_CTYPE environment variables +to an appropriate local. The locale C<C.UTF-8> is available on most systems +if one wants correct output without changing the other things locales affect, +such as collation. + +The backward-compatible output format used in Pod::Man versions before 5.00 is +available by setting the C<encoding> option to C<roff>. This may produce +marginally nicer results on older UNIX versions that do not use B<groff> or +B<mandoc>, but none of the available options will correctly render Unicode +characters on those systems. + +Below are some additional details about how this choice was made and some +discussion of alternatives. + +=head2 History + +The default output encoding for Pod::Man has been a long-standing problem. +B<troff> and B<nroff> predate Unicode by a significant margin, and their +implementations for many UNIX systems reflect that legacy. It's common for +Unicode to not be supported in any form. + +Because of this, versions of Pod::Man prior to 5.00 maintained the highly +conservative output of the original pod2man, which output pure ASCII with +complex macros to simulate common western European accented characters when +processed with troff. The nroff output was awkward and sometimes incorrect, +and characters not used in western European scripts were replaced with C<X>. +This choice maximized backwards compatibility with B<man> and +B<nroff>/B<troff> implementations at the cost of incorrect rendering of many +POD documents, particularly those containing people's names. + +The modern implementations, B<groff> (used in most Linux distributions) and +B<mandoc> (used by most BSD variants), do now support Unicode. Other UNIX +systems often do not, but they're now a tiny minority of the systems people +use on a daily basis. It's increasingly common (for very good reasons) to use +Unicode characters for POD documents rather than using ASCII conversions of +people's names or avoiding non-English text, making the limitations in the old +output format more apparent. + +Four options have been proposed to fix this: + +=over 2 + +=item * + +Optionally support UTF-8 output but don't change the default. This is the +approach taken since Pod::Man 2.1.0, which added the C<utf8> option. Some +Pod::Man users use this option for better output on platforms known to support +Unicode, but since the defaults have not changed, people continued to +encounter (and file bug reports about) the poor default rendering. + +=item * + +Convert characters to troff C<\(xx> escapes. This requires maintaining a +large translation table and addresses only a tiny part of the problem, since +many Unicode characters have no standard troff name. B<groff> has the largest +list, but if one is willing to assume B<groff> is the formatter, the next +option is better. + +=item * + +Convert characters to groff C<\[uNNNN]> escapes. This is implemented as the +C<groff> encoding for those who want to use it, and is supported by both +B<groff> and B<mandoc>. However, it is no better than UTF-8 output for +portability to other implementations. See L</Testing results> for more +details. + +=item * + +Change the default output format to UTF-8 and ask those who want maximum +backward compatibility to explicitly select the old encoding. This fixes the +issue for most users at the cost of backwards compatibility. While the +rendering of non-ASCII characters is different on older systems that don't +support UTF-8, it's not always worse than the old output. + +=back + +Pod::Man 5.00 and later makes the last choice. This arguably produces worse +output when manual pages are formatted with B<troff> into PostScript or PDF, +but doing this is rare and normally manual, so the encoding can be changed in +those cases. The older output encoding is available by setting C<encoding> to +C<roff>. + +=head2 Testing results + +Here is the results of testing C<encoding> values of C<utf-8> and C<groff> on +various operating systems. The testing methodology was to create F<man/man1> +in the current directory, copy F<encoding.utf8> or F<encoding.groff> from the +podlators 5.00 distribution to F<man/man1/encoding.1>, and then run: + + LANG=C.UTF-8 MANPATH=$(pwd)/man man 1 encoding + +If the locale is not explicitly set to one that includes UTF-8, the Unicode +characters were usually converted to ASCII (by, for example, dropping an +accent) or deleted or replaced with C<< <?> >> if there was no conversion. + +Tested on 2022-09-25. Many thanks to the GCC Compile Farm project for access +to testing hosts. + + OS UTF-8 groff + ------------------ ------- ------- + AIX 7.1 no [1] no [2] + Alpine 3.15.0 yes yes + CentOS 7.9 yes yes + Debian 7 yes yes + FreeBSD 13.0 yes yes + NetBSD 9.2 yes yes + OpenBSD 7.1 yes yes + openSUSE Leap 15.4 yes yes + Solaris 10 yes no [2] + Solaris 11 no [3] no [3] + +I did not have access to a macOS system for testing, but since it uses +B<mandoc>, it's behavior is probably the same as the BSD hosts. + +Notes: + +=over 4 + +=item [1] + +Unicode characters were converted to one or two random ASCII characters +unrelated to the original character. + +=item [2] + +Unicode characters were shown as the body of the groff escape rather than the +indicated character (in other words, text like C<[u00EF]>). + +=item [3] + +Unicode characters were deleted entirely, as if they weren't there. Using +C<nroff -man> instead of B<man> to format the page showed the same results as +Solaris 10. Using C<groff -k -man -Tutf8> to format the page produced the +correct output. + +=back + +PostScript and PDF output using groff on a Debian 12 system do not support +combining accent marks or SMP characters due to a lack of support in the +default output font. + +Testing on additional platforms is welcome. Please let the author know if you +have additional results. =head1 DIAGNOSTICS @@ -1922,9 +2236,9 @@ option was set to C<die>. =item PERL_CORE -If set and Encode is not available, silently fall back to non-UTF-8 mode -without complaining to standard error. This environment variable is set -during Perl core builds, which build Encode after podlators. Encode is +If set and Encode is not available, silently fall back to an encoding of +C<groff> without complaining to standard error. This environment variable is +set during Perl core builds, which build Encode after podlators. Encode is expected to not (yet) be available in that case. =item POD_MAN_DATE @@ -1953,65 +2267,104 @@ reliable if this variable overrode the timestamp of the input file.) =back -=head1 BUGS +=head1 COMPATIBILITY -Encoding handling assumes that PerlIO is available and does not work -properly if it isn't. The C<utf8> option is therefore not supported -unless Perl is built with PerlIO support. +Pod::Man 1.02 (based on L<Pod::Parser>) was the first version included with +Perl, in Perl 5.6.0. -There is currently no way to turn off the guesswork that tries to format -unmarked text appropriately, and sometimes it isn't wanted (particularly -when using POD to document something other than Perl). Most of the work -toward fixing this has now been done, however, and all that's still needed -is a user interface. +The current API based on L<Pod::Simple> was added in Pod::Man 2.00. Pod::Man +2.04 was included in Perl 5.9.3, the first version of Perl to incorporate +those changes. This is the first version that correctly supports all modern +POD syntax. The parse_from_filehandle() method was re-added for backward +compatibility in Pod::Man 2.09, included in Perl 5.9.4. -The NAME section should be recognized specially and index entries emitted -for everything in that section. This would have to be deferred until the -next section, since extraneous things in NAME tends to confuse various man -page processors. Currently, no index entries are emitted for anything in -NAME. +Support for anchor text in LZ<><> links of type URL was added in Pod::Man +2.23, included in Perl 5.11.5. -Pod::Man doesn't handle font names longer than two characters. Neither do -most B<troff> implementations, but GNU troff does as an extension. It would -be nice to support as an option for those who want to use it. +parse_lines(), parse_string_document(), and parse_file() set a default output +file handle of C<STDOUT> if one was not already set as of Pod::Man 2.28, +included in Perl 5.19.5. + +Support for SOURCE_DATE_EPOCH and POD_MAN_DATE was added in Pod::Man 4.00, +included in Perl 5.23.7, and generated dates were changed to use UTC instead +of the local time zone. This is also the first release that aligned the +module version and the version of the podlators distribution. All modules +included in podlators, and the podlators distribution itself, share the same +version number from this point forward. -The preamble added to each output file is rather verbose, and most of it -is only necessary in the presence of non-ASCII characters. It would -ideally be nice if all of those definitions were only output if needed, -perhaps on the fly as the characters are used. +Pod::Man 4.10, included in Perl 5.27.8, changed the formatting for manual page +references and function names to bold instead of italic, following the current +Linux manual page standard. -Pod::Man is excessively slow. +Pod::Man 5.00 changed the default output encoding to UTF-8, overridable with +the new C<encoding> option. It also fixed problems with bold or italic +extending too far when used with CZ<><> escapes, and began converting Unicode +zero-width spaces (U+200B) to the C<\:> *roff escape. It also dropped +attempts to add subtle formatting corrections in the output that would only be +visible when typeset with B<troff>, which had previously been a significant +source of bugs. + +=head1 BUGS + +There are numerous bugs and language-specific assumptions in the nroff +fallbacks for accented characters in the C<roff> encoding. Since the point of +this encoding is backward compatibility with the output from earlier versions +of Pod::Man, and it is deprecated except when necessary to support old +systems, those bugs are unlikely to ever be fixed. + +Pod::Man doesn't handle font names longer than two characters. Neither do +most B<troff> implementations, but groff does as an extension. It would be +nice to support as an option for those who want to use it. =head1 CAVEATS -If Pod::Man is given the C<utf8> option, the encoding of its output file -handle will be forced to UTF-8 if possible, overriding any existing -encoding. This will be done even if the file handle is not created by -Pod::Man and was passed in from outside. This maintains consistency -regardless of PERL_UNICODE and other settings. +=head2 Sentence spacing + +Pod::Man copies the input spacing verbatim to the output *roff document. This +means your output will be affected by how B<nroff> generally handles sentence +spacing. + +B<nroff> dates from an era in which it was standard to use two spaces after +sentences, and will always add two spaces after a line-ending period (or +similar punctuation) when reflowing text. For example, the following input: + + =pod -The handling of hyphens and em dashes is somewhat fragile, and one may get -the wrong one under some circumstances. This should only matter for -B<troff> output. + One sentence. + Another sentence. -When and whether to use small caps is somewhat tricky, and Pod::Man doesn't -necessarily get it right. +will result in two spaces after the period when the text is reflowed. If you +use two spaces after sentences anyway, this will be consistent, although you +will have to be careful to not end a line with an abbreviation such as C<e.g.> +or C<Ms.>. Output will also be consistent if you use the *roff style guide +(and L<XKCD 1285|https://xkcd.com/1285/>) recommendation of putting a line +break after each sentence, although that will consistently produce two spaces +after each sentence, which may not be what you want. -Converting neutral double quotes to properly matched double quotes doesn't -work unless there are no formatting codes between the quote marks. This -only matters for troff output. +If you prefer one space after sentences (which is the more modern style), you +will unfortunately need to ensure that no line in the middle of a paragraph +ends in a period or similar sentence-ending paragraph. Otherwise, B<nroff> +will add a two spaces after that sentence when reflowing, and your output +document will have inconsistent spacing. + +=head2 Hyphens + +The handling of hyphens versus dashes is somewhat fragile, and one may get a +the wrong one under some circumstances. This will normally only matter for +line breaking and possibly for troff output. =head1 AUTHOR -Russ Allbery <rra@cpan.org>, based I<very> heavily on the original B<pod2man> -by Tom Christiansen <tchrist@mox.perl.com>. The modifications to work with -Pod::Simple instead of Pod::Parser were originally contributed by Sean Burke -<sburke@cpan.org> (but I've since hacked them beyond recognition and all bugs -are mine). +Written by Russ Allbery <rra@cpan.org>, based on the original B<pod2man> by +Tom Christiansen <tchrist@mox.perl.com>. + +The modifications to work with Pod::Simple instead of Pod::Parser were +contributed by Sean Burke <sburke@cpan.org>, but I've since hacked them beyond +recognition and all bugs are mine. =head1 COPYRIGHT AND LICENSE -Copyright 1999-2010, 2012-2019 Russ Allbery <rra@cpan.org> +Copyright 1999-2010, 2012-2020, 2022 Russ Allbery <rra@cpan.org> Substantial contributions by Sean Burke <sburke@cpan.org>. @@ -2020,18 +2373,19 @@ under the same terms as Perl itself. =head1 SEE ALSO -L<Pod::Simple>, L<perlpod(1)>, L<pod2man(1)>, L<nroff(1)>, L<troff(1)>, -L<man(1)>, L<man(7)> +L<Encode::Supported>, L<Pod::Simple>, L<perlpod(1)>, L<pod2man(1)>, +L<nroff(1)>, L<troff(1)>, L<man(1)>, L<man(7)> Ossanna, Joseph F., and Brian W. Kernighan. "Troff User's Manual," Computing Science Technical Report No. 54, AT&T Bell Laboratories. This is the best documentation of standard B<nroff> and B<troff>. At the time of this writing, it's available at L<http://www.troff.org/54.pdf>. -The man page documenting the man macro set may be L<man(5)> instead of -L<man(7)> on your system. Also, please see L<pod2man(1)> for extensive -documentation on writing manual pages if you've not done it before and -aren't familiar with the conventions. +The manual page documenting the man macro set may be L<man(5)> instead of +L<man(7)> on your system. + +See L<perlpodstyle(1)> for documentation on writing manual pages in POD if +you've not done it before and aren't familiar with the conventions. The current version of this module is always available from its web site at L<https://www.eyrie.org/~eagle/software/podlators/>. It is also part of the diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/ParseLink.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/ParseLink.pm index 273c95847a..83bc3f7565 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/ParseLink.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/ParseLink.pm @@ -13,17 +13,15 @@ package Pod::ParseLink; -use 5.008; +use 5.010; use strict; use warnings; -use vars qw(@EXPORT @ISA $VERSION); - use Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(parselink); -$VERSION = '4.14'; +our @ISA = qw(Exporter); +our @EXPORT = qw(parselink); +our $VERSION = '5.01'; ############################################################################## # Implementation @@ -171,7 +169,7 @@ Russ Allbery <rra@cpan.org> =head1 COPYRIGHT AND LICENSE -Copyright 2001, 2008, 2009, 2014, 2018-2019 Russ Allbery <rra@cpan.org> +Copyright 2001, 2008, 2009, 2014, 2018-2019, 2022 Russ Allbery <rra@cpan.org> This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple.pm index f2544d0ef1..ee89c0a489 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple.pm @@ -8,6 +8,7 @@ use integer; use Pod::Escapes 1.04 (); use Pod::Simple::LinkSection (); use Pod::Simple::BlackBox (); +use Pod::Simple::TiedOutFH; #use utf8; use vars qw( @@ -18,7 +19,7 @@ use vars qw( ); @ISA = ('Pod::Simple::BlackBox'); -$VERSION = '3.42'; +$VERSION = '3.43'; @Known_formatting_codes = qw(I B C L E F S X Z); %Known_formatting_codes = map(($_=>1), @Known_formatting_codes); @@ -202,7 +203,6 @@ sub output_string { my $this = shift; return $this->{'output_string'} unless @_; # GET. - require Pod::Simple::TiedOutFH; my $x = (defined($_[0]) and ref($_[0])) ? $_[0] : \( $_[0] ); $$x = '' unless defined $$x; DEBUG > 4 and print STDERR "# Output string set to $x ($$x)\n"; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/BlackBox.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/BlackBox.pm index 03dede7c34..7c0d9aa469 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/BlackBox.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/BlackBox.pm @@ -22,7 +22,7 @@ use integer; # vroom! use strict; use Carp (); use vars qw($VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; #use constant DEBUG => 7; sub my_qr ($$) { diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Checker.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Checker.pm index 65f4d54243..3b22a3d6cd 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Checker.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Checker.pm @@ -9,7 +9,7 @@ use Carp (); use Pod::Simple::Methody (); use Pod::Simple (); use vars qw( @ISA $VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; @ISA = ('Pod::Simple::Methody'); BEGIN { *DEBUG = defined(&Pod::Simple::DEBUG) ? \&Pod::Simple::DEBUG diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Debug.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Debug.pm index 6b9aa327c0..7f51efa9dc 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Debug.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Debug.pm @@ -2,7 +2,7 @@ require 5; package Pod::Simple::Debug; use strict; use vars qw($VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; sub import { my($value,$variable); diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsText.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsText.pm index a22603043b..dfcee5d2b4 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsText.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsText.pm @@ -1,7 +1,7 @@ require 5; package Pod::Simple::DumpAsText; -$VERSION = '3.42'; +$VERSION = '3.43'; use Pod::Simple (); BEGIN {@ISA = ('Pod::Simple')} diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsXML.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsXML.pm index 024e4b7b81..c5e719cdf8 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsXML.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/DumpAsXML.pm @@ -1,7 +1,7 @@ require 5; package Pod::Simple::DumpAsXML; -$VERSION = '3.42'; +$VERSION = '3.43'; use Pod::Simple (); BEGIN {@ISA = ('Pod::Simple')} diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTML.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTML.pm index f930a51217..cebf5702a8 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTML.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTML.pm @@ -9,7 +9,7 @@ use vars qw( $Doctype_decl $Content_decl ); @ISA = ('Pod::Simple::PullParser'); -$VERSION = '3.42'; +$VERSION = '3.43'; BEGIN { if(defined &DEBUG) { } # no-op elsif( defined &Pod::Simple::DEBUG ) { *DEBUG = \&Pod::Simple::DEBUG } diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTMLBatch.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTMLBatch.pm index 6a06173f47..cd33a4c97c 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTMLBatch.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/HTMLBatch.pm @@ -5,7 +5,7 @@ use strict; use vars qw( $VERSION $HTML_RENDER_CLASS $HTML_EXTENSION $CSS $JAVASCRIPT $SLEEPY $SEARCH_CLASS @ISA ); -$VERSION = '3.42'; +$VERSION = '3.43'; @ISA = (); # Yup, we're NOT a subclass of Pod::Simple::HTML! # TODO: nocontents stylesheets. Strike some of the color variations? diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/LinkSection.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/LinkSection.pm index a6898caec4..c14dabcea2 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/LinkSection.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/LinkSection.pm @@ -6,7 +6,7 @@ package Pod::Simple::LinkSection; use strict; use Pod::Simple::BlackBox; use vars qw($VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; use overload( # So it'll stringify nice '""' => \&Pod::Simple::BlackBox::stringify_lol, diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Methody.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Methody.pm index 45e26cf463..cc096facbb 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Methody.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Methody.pm @@ -4,7 +4,7 @@ package Pod::Simple::Methody; use strict; use Pod::Simple (); use vars qw(@ISA $VERSION); -$VERSION = '3.42'; +$VERSION = '3.43'; @ISA = ('Pod::Simple'); # Yes, we could use named variables, but I want this to be impose diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Progress.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Progress.pm index 77de9ae86f..d1eaba2d6f 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Progress.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Progress.pm @@ -1,7 +1,7 @@ require 5; package Pod::Simple::Progress; -$VERSION = '3.42'; +$VERSION = '3.43'; use strict; # Objects of this class are used for noting progress of an diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParser.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParser.pm index 57aad9ac08..8c00592fba 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParser.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParser.pm @@ -1,6 +1,6 @@ require 5; package Pod::Simple::PullParser; -$VERSION = '3.42'; +$VERSION = '3.43'; use Pod::Simple (); BEGIN {@ISA = ('Pod::Simple')} diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserEndToken.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserEndToken.pm index dbff3df249..2d656e088f 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserEndToken.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserEndToken.pm @@ -5,7 +5,7 @@ use Pod::Simple::PullParserToken (); use strict; use vars qw(@ISA $VERSION); @ISA = ('Pod::Simple::PullParserToken'); -$VERSION = '3.42'; +$VERSION = '3.43'; sub new { # Class->new(tagname); my $class = shift; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserStartToken.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserStartToken.pm index 1ab33cc6e0..5e1bf71ed9 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserStartToken.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserStartToken.pm @@ -5,7 +5,7 @@ use Pod::Simple::PullParserToken (); use strict; use vars qw(@ISA $VERSION); @ISA = ('Pod::Simple::PullParserToken'); -$VERSION = '3.42'; +$VERSION = '3.43'; sub new { # Class->new(tagname, optional_attrhash); my $class = shift; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserTextToken.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserTextToken.pm index cdce959db4..159839952e 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserTextToken.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserTextToken.pm @@ -5,7 +5,7 @@ use Pod::Simple::PullParserToken (); use strict; use vars qw(@ISA $VERSION); @ISA = ('Pod::Simple::PullParserToken'); -$VERSION = '3.42'; +$VERSION = '3.43'; sub new { # Class->new(text); my $class = shift; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserToken.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserToken.pm index 63a2dabe6f..48cece540f 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserToken.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/PullParserToken.pm @@ -3,7 +3,7 @@ require 5; package Pod::Simple::PullParserToken; # Base class for tokens gotten from Pod::Simple::PullParser's $parser->get_token @ISA = (); -$VERSION = '3.42'; +$VERSION = '3.43'; use strict; sub new { # Class->new('type', stuff...); ## Overridden in derived classes anyway diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/RTF.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/RTF.pm index 10e05c5d0a..793a8b2a49 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/RTF.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/RTF.pm @@ -8,7 +8,7 @@ package Pod::Simple::RTF; use strict; use vars qw($VERSION @ISA %Escape $WRAP %Tagmap); -$VERSION = '3.42'; +$VERSION = '3.43'; use Pod::Simple::PullParser (); BEGIN {@ISA = ('Pod::Simple::PullParser')} diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Search.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Search.pm index ad610654c9..6462549492 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Search.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Search.pm @@ -3,7 +3,7 @@ package Pod::Simple::Search; use strict; use vars qw($VERSION $MAX_VERSION_WITHIN $SLEEPY); -$VERSION = '3.42'; ## Current version of this package +$VERSION = '3.43'; ## Current version of this package BEGIN { *DEBUG = sub () {0} unless defined &DEBUG; } # set DEBUG level use Carp (); diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/SimpleTree.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/SimpleTree.pm index 38a2704f87..15f457baaf 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/SimpleTree.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/SimpleTree.pm @@ -5,7 +5,7 @@ use strict; use Carp (); use Pod::Simple (); use vars qw( $ATTR_PAD @ISA $VERSION $SORT_ATTRS); -$VERSION = '3.42'; +$VERSION = '3.43'; BEGIN { @ISA = ('Pod::Simple'); *DEBUG = \&Pod::Simple::DEBUG unless defined &DEBUG; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Text.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Text.pm index 2f0254ec37..f44987f4e4 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Text.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Text.pm @@ -6,7 +6,7 @@ use Carp (); use Pod::Simple::Methody (); use Pod::Simple (); use vars qw( @ISA $VERSION $FREAKYMODE); -$VERSION = '3.42'; +$VERSION = '3.43'; @ISA = ('Pod::Simple::Methody'); BEGIN { *DEBUG = defined(&Pod::Simple::DEBUG) ? \&Pod::Simple::DEBUG diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TextContent.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TextContent.pm index ccbf424221..9c2932e37d 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TextContent.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TextContent.pm @@ -6,7 +6,7 @@ use strict; use Carp (); use Pod::Simple (); use vars qw( @ISA $VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; @ISA = ('Pod::Simple'); sub new { diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TiedOutFH.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TiedOutFH.pm index cbf58b3706..af5e745a30 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TiedOutFH.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TiedOutFH.pm @@ -4,7 +4,7 @@ package Pod::Simple::TiedOutFH; use Symbol ('gensym'); use Carp (); use vars qw($VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Transcode.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Transcode.pm index bdb7181af6..fef5d17d45 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Transcode.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/Transcode.pm @@ -3,7 +3,7 @@ require 5; package Pod::Simple::Transcode; use strict; use vars qw($VERSION @ISA); -$VERSION = '3.42'; +$VERSION = '3.43'; BEGIN { if(defined &DEBUG) {;} # Okay diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeDumb.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeDumb.pm index 96e6a54410..776b067645 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeDumb.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeDumb.pm @@ -5,7 +5,7 @@ require 5; package Pod::Simple::TranscodeDumb; use strict; use vars qw($VERSION %Supported); -$VERSION = '3.42'; +$VERSION = '3.43'; # This module basically pretends it knows how to transcode, except # only for null-transcodings! We use this when Encode isn't # available. diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeSmart.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeSmart.pm index 3f3224f917..f46d1f9d05 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeSmart.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/TranscodeSmart.pm @@ -9,7 +9,7 @@ use strict; use Pod::Simple; require Encode; use vars qw($VERSION ); -$VERSION = '3.42'; +$VERSION = '3.43'; sub is_dumb {0} sub is_smart {1} diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XHTML.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XHTML.pm index 9049ce755f..e8d7e11127 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XHTML.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XHTML.pm @@ -45,7 +45,7 @@ declare the output character set as UTF-8 before parsing, like so: package Pod::Simple::XHTML; use strict; use vars qw( $VERSION @ISA $HAS_HTML_ENTITIES ); -$VERSION = '3.42'; +$VERSION = '3.43'; use Pod::Simple::Methody (); @ISA = ('Pod::Simple::Methody'); diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XMLOutStream.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XMLOutStream.pm index a891a3341f..74d8c16b7b 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XMLOutStream.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Simple/XMLOutStream.pm @@ -5,7 +5,7 @@ use strict; use Carp (); use Pod::Simple (); use vars qw( $ATTR_PAD @ISA $VERSION $SORT_ATTRS); -$VERSION = '3.42'; +$VERSION = '3.43'; BEGIN { @ISA = ('Pod::Simple'); *DEBUG = \&Pod::Simple::DEBUG unless defined &DEBUG; diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text.pm index 56e6e78a86..83a7ce22a8 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text.pm @@ -14,23 +14,20 @@ package Pod::Text; -use 5.008; +use 5.010; use strict; use warnings; -use vars qw(@ISA @EXPORT %ESCAPES $VERSION); - use Carp qw(carp croak); use Encode qw(encode); use Exporter (); use Pod::Simple (); -@ISA = qw(Pod::Simple Exporter); +our @ISA = qw(Pod::Simple Exporter); +our $VERSION = '5.01'; # We have to export pod2text for backward compatibility. -@EXPORT = qw(pod2text); - -$VERSION = '4.14'; +our @EXPORT = qw(pod2text); # Ensure that $Pod::Simple::nbsp and $Pod::Simple::shy are available. Code # taken from Pod::Simple 3.32, but was only added in 3.30. @@ -43,6 +40,11 @@ if ($Pod::Simple::VERSION ge 3.30) { $SHY = chr utf8::unicode_to_native(0xAD); } +# Import the ASCII constant from Pod::Simple. This is true iff we're in an +# ASCII-based universe (including such things as ISO 8859-1 and UTF-8), and is +# generally only false for EBCDIC. +BEGIN { *ASCII = \&Pod::Simple::ASCII } + ############################################################################## # Initialization ############################################################################## @@ -64,9 +66,6 @@ sub new { my $class = shift; my $self = $class->SUPER::new; - # Tell Pod::Simple to handle S<> by automatically inserting . - $self->nbsp_for_S (1); - # Tell Pod::Simple to keep whitespace whenever possible. if ($self->can ('preserve_whitespace')) { $self->preserve_whitespace (1); @@ -89,16 +88,20 @@ sub new { my @opts = map { ("opt_$_", $opts{$_}) } keys %opts; %$self = (%$self, @opts); - # Send errors to stderr if requested. + # Backwards-compatibility support for the stderr option. if ($$self{opt_stderr} and not $$self{opt_errors}) { $$self{opt_errors} = 'stderr'; } delete $$self{opt_stderr}; - # Validate the errors parameter and act on it. - if (not defined $$self{opt_errors}) { - $$self{opt_errors} = 'pod'; + # Backwards-compatibility support for the utf8 option. + if ($$self{opt_utf8} && !$$self{opt_encoding}) { + $$self{opt_encoding} = 'UTF-8'; } + delete $$self{opt_utf8}; + + # Validate the errors parameter and act on it. + $$self{opt_errors} //= 'pod'; if ($$self{opt_errors} eq 'stderr' || $$self{opt_errors} eq 'die') { $self->no_errata_section (1); $self->complain_stderr (1); @@ -117,12 +120,12 @@ sub new { delete $$self{errors}; # Initialize various things from our parameters. - $$self{opt_alt} = 0 unless defined $$self{opt_alt}; - $$self{opt_indent} = 4 unless defined $$self{opt_indent}; - $$self{opt_margin} = 0 unless defined $$self{opt_margin}; - $$self{opt_loose} = 0 unless defined $$self{opt_loose}; - $$self{opt_sentence} = 0 unless defined $$self{opt_sentence}; - $$self{opt_width} = 76 unless defined $$self{opt_width}; + $$self{opt_alt} //= 0; + $$self{opt_indent} //= 4; + $$self{opt_margin} //= 0; + $$self{opt_loose} //= 0; + $$self{opt_sentence} //= 0; + $$self{opt_width} //= 76; # Figure out what quotes we'll be using for C<> text. $$self{opt_quotes} ||= '"'; @@ -138,6 +141,17 @@ sub new { croak qq(Invalid quote specification "$$self{opt_quotes}"); } + # Configure guesswork based on options. + my $guesswork = $self->{opt_guesswork} || q{}; + my %guesswork = map { $_ => 1 } split(m{,}xms, $guesswork); + if (!%guesswork || $guesswork{all}) { + $$self{GUESSWORK} = {quoting => 1}; + } elsif ($guesswork{none}) { + $$self{GUESSWORK} = {}; + } else { + $$self{GUESSWORK} = {%guesswork}; + } + # If requested, do something with the non-POD text. $self->code_handler (\&handle_code) if $$self{opt_code}; @@ -272,9 +286,7 @@ sub reformat { } # Output text to the output device. Replace non-breaking spaces with spaces -# and soft hyphens with nothing, and then try to fix the output encoding if -# necessary to match the input encoding unless UTF-8 output is forced. This -# preserves the traditional pass-through behavior of Pod::Text. +# and soft hyphens with nothing, and then determine the output encoding. sub output { my ($self, @text) = @_; my $text = join ('', @text); @@ -284,15 +296,39 @@ sub output { if ($SHY) { $text =~ s/$SHY//g; } - unless ($$self{opt_utf8}) { - my $encoding = $$self{encoding} || ''; - if ($encoding && $encoding ne $$self{ENCODING}) { - $$self{ENCODING} = $encoding; - eval { binmode ($$self{output_fh}, ":encoding($encoding)") }; - } - } + + # The logic used here is described in the POD documentation. Prefer the + # configured encoding, then the pass-through option of using the same + # encoding as the input, and then UTF-8, but commit to an encoding for the + # document. + # + # ENCODE says whether to encode or not and is turned off if there is a + # PerlIO encoding layer (in start_document). ENCODING is the encoding + # that we previously committed to and is cleared at the start of each + # document. if ($$self{ENCODE}) { - print { $$self{output_fh} } encode ('UTF-8', $text); + my $encoding = $$self{ENCODING}; + if (!$encoding) { + $encoding = $self->encoding(); + if (!$encoding && ASCII && $text =~ /[^\x00-\x7F]/) { + $encoding = 'UTF-8'; + } + if ($encoding) { + $$self{ENCODING} = $encoding; + } + } + if ($encoding) { + my $check = sub { + my ($char) = @_; + my $display = '"\x{' . hex($char) . '}"'; + my $error = "$display does not map to $$self{ENCODING}"; + $self->whine ($self->line_count(), $error); + return Encode::encode ($$self{ENCODING}, chr($char)); + }; + print { $$self{output_fh} } encode ($encoding, $text, $check); + } else { + print { $$self{output_fh} } $text; + } } else { print { $$self{output_fh} } $text; } @@ -322,24 +358,18 @@ sub start_document { $$self{MARGIN} = $margin; # Default left margin. $$self{PENDING} = [[]]; # Pending output. - # We have to redo encoding handling for each document. - $$self{ENCODING} = ''; - - # When UTF-8 output is set, check whether our output file handle already - # has a PerlIO encoding layer set. If it does not, we'll need to encode - # our output before printing it (handled in the output() sub). - $$self{ENCODE} = 0; - if ($$self{opt_utf8}) { - $$self{ENCODE} = 1; - eval { - my @options = (output => 1, details => 1); - my $flag = (PerlIO::get_layers ($$self{output_fh}, @options))[-1]; - if ($flag && ($flag & PerlIO::F_UTF8 ())) { - $$self{ENCODE} = 0; - $$self{ENCODING} = 'UTF-8'; - } - }; - } + # We have to redo encoding handling for each document. Check whether the + # output file handle already has a PerlIO encoding layer set and, if so, + # disable encoding. + $$self{ENCODE} = 1; + eval { + my @options = (output => 1, details => 1); + my $flag = (PerlIO::get_layers ($$self{output_fh}, @options))[-1]; + if ($flag && ($flag & PerlIO::F_UTF8 ())) { + $$self{ENCODE} = 0; + } + }; + $$self{ENCODING} = $$self{opt_encoding}; return ''; } @@ -383,8 +413,7 @@ sub item { # Calculate the indentation and margin. $fits is set to true if the tag # will fit into the margin of the paragraph given our indentation level. - my $indent = $$self{INDENTS}[-1]; - $indent = $$self{opt_indent} unless defined $indent; + my $indent = $$self{INDENTS}[-1] // $$self{opt_indent}; my $margin = ' ' x $$self{opt_margin}; my $tag_length = length ($self->strip_format ($tag)); my $fits = ($$self{MARGIN} - $indent >= $tag_length + 1); @@ -588,6 +617,13 @@ sub cmd_f { return $_[0]{alt} ? "\"$_[2]\"" : $_[2] } sub cmd_i { return '*' . $_[2] . '*' } sub cmd_x { return '' } +# Convert all internal whitespace to $NBSP. +sub cmd_s { + my ($self, $attrs, $text) = @_; + $text =~ s{ \s }{$NBSP}xmsg; + return $text; +} + # Apply a whole bunch of messy heuristics to not quote things that don't # benefit from being quoted. These originally come from Barrie Slaymaker and # largely duplicate code in Pod::Man. @@ -597,23 +633,35 @@ sub cmd_c { # A regex that matches the portion of a variable reference that's the # array or hash index, separated out just because we want to use it in # several places in the following regex. - my $index = '(?: \[.*\] | \{.*\} )?'; + my $index = '(?: \[[^]]+\] | \{[^}]+\} )?'; # Check for things that we don't want to quote, and if we find any of # them, return the string with just a font change and no quoting. + # + # Traditionally, Pod::Text has not quoted Perl variables, functions, + # numbers, or hex constants, but this is not always desirable. Make this + # optional on the quoting guesswork flag. + my $extra = qr{(?!)}xms; # never matches + if ($$self{GUESSWORK}{quoting}) { + $extra = qr{ + \$+ [\#^]? \S $index # special ($^F, $") + | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func + | [\$\@%&*]* [:\'\w]+ + (?: -> )? \(\s*[^\s,\)]*\s*\) # 0/1-arg func call + | [+-]? ( \d[\d.]* | \.\d+ ) + (?: [eE][+-]?\d+ )? # a number + | 0x [a-fA-F\d]+ # a hex constant + }xms; + } $text =~ m{ ^\s* (?: - ( [\'\`\"] ) .* \1 # already quoted - | \` .* \' # `quoted' - | \$+ [\#^]? \S $index # special ($^Foo, $") - | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func - | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call - | [+-]? ( \d[\d.]* | \.\d+ ) (?: [eE][+-]?\d+ )? # a number - | 0x [a-fA-F\d]+ # a hex constant + ( [\'\`\"] ) .* \1 # already quoted + | \` .* \' # `quoted' + | $extra ) \s*\z - }xo && return $text; + }xms and return $text; # If we didn't return, go ahead and quote the text. return $$self{opt_alt} @@ -766,7 +814,7 @@ __END__ =for stopwords alt stderr Allbery Sean Burke's Christiansen UTF-8 pre-Unicode utf8 nourls -parsers +parsers EBCDIC autodetecting superset unrepresentable FH NNN =head1 NAME @@ -785,67 +833,180 @@ Pod::Text - Convert POD data to formatted text =head1 DESCRIPTION -Pod::Text is a module that can convert documentation in the POD format -(the preferred language for documenting Perl) into formatted text. It -uses no special formatting controls or codes whatsoever, and its output is -therefore suitable for nearly any device. +Pod::Text is a module that can convert documentation in the POD format (the +preferred language for documenting Perl) into formatted text. It uses no +special formatting controls or codes, and its output is therefore suitable for +nearly any device. -As a derived class from Pod::Simple, Pod::Text supports the same methods and -interfaces. See L<Pod::Simple> for all the details; briefly, one creates a -new parser with C<< Pod::Text->new() >> and then normally calls parse_file(). +=head2 Encoding -new() can take options, in the form of key/value pairs, that control the -behavior of the parser. The currently recognized options are: +Pod::Text uses the following logic to choose an output encoding, in order: + +=over 4 + +=item 1. + +If a PerlIO encoding layer is set on the output file handle, do not do any +output encoding and will instead rely on the PerlIO encoding layer. + +=item 2. + +If the C<encoding> or C<utf8> options are set, use the output encoding +specified by those options. + +=item 3. + +If the input encoding of the POD source file was explicitly specified (using +C<=encoding>) or automatically detected by Pod::Simple, use that as the output +encoding as well. + +=item 4. + +Otherwise, if running on a non-EBCDIC system, use UTF-8 as the output +encoding. Since this is a superset of ASCII, this will result in ASCII output +unless the POD input contains non-ASCII characters without declaring or +autodetecting an encoding (usually via EZ<><> escapes). + +=item 5. + +Otherwise, for EBCDIC systems, output without doing any encoding and hope +this works. + +=back + +One caveat: Pod::Text has to commit to an output encoding the first time it +outputs a non-ASCII character, and then has to stick with it for consistency. +However, C<=encoding> commands don't have to be at the beginning of a POD +document. If someone uses a non-ASCII character early in a document with an +escape, such as EZ<><0xEF>, and then puts C<=encoding iso-8859-1> later, +ideally Pod::Text would follow rule 3 and output the entire document as ISO +8859-1. Instead, it will commit to UTF-8 following rule 4 as soon as it sees +that escape, and then stick with that encoding for the rest of the document. + +Unfortunately, there's no universally good choice for an output encoding. +Each choice will be incorrect in some circumstances. This approach was chosen +primarily for backwards compatibility. Callers should consider forcing the +output encoding via C<encoding> if they have any knowledge about what encoding +the user may expect. + +In particular, consider importing the L<Encode::Locale> module, if available, +and setting C<encoding> to C<locale> to use an output encoding appropriate to +the user's locale. But be aware that if the user is not using locales or is +using a locale of C<C>, Encode::Locale will set the output encoding to +US-ASCII. This will cause all non-ASCII characters will be replaced with C<?> +and produce a flurry of warnings about unsupported characters, which may or +may not be what you want. + +=head1 CLASS METHODS + +=over 4 + +=item new(ARGS) + +Create a new Pod::Text object. ARGS should be a list of key/value pairs, +where the keys are chosen from the following. Each option is annotated with +the version of Pod::Text in which that option was added with its current +meaning. =over 4 =item alt -If set to a true value, selects an alternate output format that, among other -things, uses a different heading style and marks C<=item> entries with a +[2.00] If set to a true value, selects an alternate output format that, among +other things, uses a different heading style and marks C<=item> entries with a colon in the left margin. Defaults to false. =item code -If set to a true value, the non-POD parts of the input file will be included -in the output. Useful for viewing code documented with POD blocks with the -POD rendered and the code left intact. +[2.13] If set to a true value, the non-POD parts of the input file will be +included in the output. Useful for viewing code documented with POD blocks +with the POD rendered and the code left intact. + +=item encoding + +[5.00] Specifies the encoding of the output. The value must be an encoding +recognized by the L<Encode> module (see L<Encode::Supported>). If the output +contains characters that cannot be represented in this encoding, that is an +error that will be reported as configured by the C<errors> option. If error +handling is other than C<die>, the unrepresentable character will be replaced +with the Encode substitution character (normally C<?>). + +If the output file handle has a PerlIO encoding layer set, this parameter will +be ignored and no encoding will be done by Pod::Man. It will instead rely on +the encoding layer to make whatever output encoding transformations are +desired. + +WARNING: The input encoding of the POD source is independent from the output +encoding, and setting this option does not affect the interpretation of the +POD input. Unless your POD source is US-ASCII, its encoding should be +declared with the C<=encoding> command in the source, as near to the top of +the file as possible. If this is not done, Pod::Simple will will attempt to +guess the encoding and may be successful if it's Latin-1 or UTF-8, but it will +produce warnings. See L<perlpod(1)> for more information. =item errors -How to report errors. C<die> says to throw an exception on any POD -formatting error. C<stderr> says to report errors on standard error, but -not to throw an exception. C<pod> says to include a POD ERRORS section -in the resulting documentation summarizing the errors. C<none> ignores -POD errors entirely, as much as possible. +[3.17] How to report errors. C<die> says to throw an exception on any POD +formatting error. C<stderr> says to report errors on standard error, but not +to throw an exception. C<pod> says to include a POD ERRORS section in the +resulting documentation summarizing the errors. C<none> ignores POD errors +entirely, as much as possible. The default is C<pod>. +=item guesswork + +[5.01] By default, Pod::Text applies some default formatting rules based on +guesswork and regular expressions that are intended to make writing Perl +documentation easier and require less explicit markup. These rules may not +always be appropriate, particularly for documentation that isn't about Perl. +This option allows turning all or some of it off. + +The special value C<all> enables all guesswork. This is also the default for +backward compatibility reasons. The special value C<none> disables all +guesswork. Otherwise, the value of this option should be a comma-separated +list of one or more of the following keywords: + +=over 4 + +=item quoting + +If no guesswork is enabled, any text enclosed in CZ<><> is surrounded by +double quotes in nroff (terminal) output unless the contents are already +quoted. When this guesswork is enabled, quote marks will also be suppressed +for Perl variables, function names, function calls, numbers, and hex +constants. + +=back + +Any unknown guesswork name is silently ignored (for potential future +compatibility), so be careful about spelling. + =item indent -The number of spaces to indent regular text, and the default indentation for -C<=over> blocks. Defaults to 4. +[2.00] The number of spaces to indent regular text, and the default +indentation for C<=over> blocks. Defaults to 4. =item loose -If set to a true value, a blank line is printed after a C<=head1> heading. -If set to false (the default), no blank line is printed after C<=head1>, -although one is still printed after C<=head2>. This is the default because -it's the expected formatting for manual pages; if you're formatting +[2.00] If set to a true value, a blank line is printed after a C<=head1> +heading. If set to false (the default), no blank line is printed after +C<=head1>, although one is still printed after C<=head2>. This is the default +because it's the expected formatting for manual pages; if you're formatting arbitrary text documents, setting this to true may result in more pleasing output. =item margin -The width of the left margin in spaces. Defaults to 0. This is the margin -for all text, including headings, not the amount by which regular text is -indented; for the latter, see the I<indent> option. To set the right +[2.21] The width of the left margin in spaces. Defaults to 0. This is the +margin for all text, including headings, not the amount by which regular text +is indented; for the latter, see the I<indent> option. To set the right margin, see the I<width> option. =item nourls -Normally, LZ<><> formatting codes with a URL but anchor text are formatted -to show both the anchor text and the URL. In other words: +[3.17] Normally, LZ<><> formatting codes with a URL but anchor text are +formatted to show both the anchor text and the URL. In other words: L<foo|http://example.com/> @@ -853,74 +1014,131 @@ is formatted as: foo <http://example.com/> -This option, if set to a true value, suppresses the URL when anchor text -is given, so this example would be formatted as just C<foo>. This can -produce less cluttered output in cases where the URLs are not particularly -important. +This option, if set to a true value, suppresses the URL when anchor text is +given, so this example would be formatted as just C<foo>. This can produce +less cluttered output in cases where the URLs are not particularly important. =item quotes -Sets the quote marks used to surround CE<lt>> text. If the value is a -single character, it is used as both the left and right quote. Otherwise, -it is split in half, and the first half of the string is used as the left -quote and the second is used as the right quote. +[4.00] Sets the quote marks used to surround CE<lt>> text. If the value is a +single character, it is used as both the left and right quote. Otherwise, it +is split in half, and the first half of the string is used as the left quote +and the second is used as the right quote. This may also be set to the special value C<none>, in which case no quote marks are added around CE<lt>> text. =item sentence -If set to a true value, Pod::Text will assume that each sentence ends in two -spaces, and will try to preserve that spacing. If set to false, all -consecutive whitespace in non-verbatim paragraphs is compressed into a -single space. Defaults to false. +[3.00] If set to a true value, Pod::Text will assume that each sentence ends +in two spaces, and will try to preserve that spacing. If set to false, all +consecutive whitespace in non-verbatim paragraphs is compressed into a single +space. Defaults to false. =item stderr -Send error messages about invalid POD to standard error instead of -appending a POD ERRORS section to the generated output. This is -equivalent to setting C<errors> to C<stderr> if C<errors> is not already -set. It is supported for backward compatibility. +[3.10] Send error messages about invalid POD to standard error instead of +appending a POD ERRORS section to the generated output. This is equivalent to +setting C<errors> to C<stderr> if C<errors> is not already set. It is +supported for backward compatibility. =item utf8 -By default, Pod::Text uses the same output encoding as the input encoding -of the POD source (provided that Perl was built with PerlIO; otherwise, it -doesn't encode its output). If this option is given, the output encoding -is forced to UTF-8. - -Be aware that, when using this option, the input encoding of your POD -source should be properly declared unless it's US-ASCII. Pod::Simple will -attempt to guess the encoding and may be successful if it's Latin-1 or -UTF-8, but it will produce warnings. Use the C<=encoding> command to -declare the encoding. See L<perlpod(1)> for more information. +[3.12] If this option is set to a true value, the output encoding is set to +UTF-8. This is equivalent to setting C<encoding> to C<UTF-8> if C<encoding> +is not already set. It is supported for backward compatibility. =item width -The column at which to wrap text on the right-hand side. Defaults to 76. +[2.00] The column at which to wrap text on the right-hand side. Defaults to +76. + +=back + +=back + +=head1 INSTANCE METHODS + +As a derived class from Pod::Simple, Pod::Text supports the same methods and +interfaces. See L<Pod::Simple> for all the details. This section summarizes +the most-frequently-used methods and the ones added by Pod::Text. + +=over 4 + +=item output_fh(FH) + +Direct the output from parse_file(), parse_lines(), or parse_string_document() +to the file handle FH instead of C<STDOUT>. + +=item output_string(REF) + +Direct the output from parse_file(), parse_lines(), or parse_string_document() +to the scalar variable pointed to by REF, rather than C<STDOUT>. For example: + + my $man = Pod::Man->new(); + my $output; + $man->output_string(\$output); + $man->parse_file('/some/input/file'); + +Be aware that the output in that variable will already be encoded (see +L</Encoding>). + +=item parse_file(PATH) + +Read the POD source from PATH and format it. By default, the output is sent +to C<STDOUT>, but this can be changed with the output_fh() or output_string() +methods. + +=item parse_from_file(INPUT, OUTPUT) + +=item parse_from_filehandle(FH, OUTPUT) + +Read the POD source from INPUT, format it, and output the results to OUTPUT. + +parse_from_filehandle() is provided for backward compatibility with older +versions of Pod::Man. parse_from_file() should be used instead. + +=item parse_lines(LINES[, ...[, undef]]) + +Parse the provided lines as POD source, writing the output to either C<STDOUT> +or the file handle set with the output_fh() or output_string() methods. This +method can be called repeatedly to provide more input lines. An explicit +C<undef> should be passed to indicate the end of input. + +This method expects raw bytes, not decoded characters. + +=item parse_string_document(INPUT) + +Parse the provided scalar variable as POD source, writing the output to either +C<STDOUT> or the file handle set with the output_fh() or output_string() +methods. + +This method expects raw bytes, not decoded characters. =back -The standard Pod::Simple method parse_file() takes one argument naming the -POD file to read from. By default, the output is sent to C<STDOUT>, but -this can be changed with the output_fh() method. +=head1 FUNCTIONS -The standard Pod::Simple method parse_from_file() takes up to two -arguments, the first being the input file to read POD from and the second -being the file to write the formatted output to. +Pod::Text exports one function for backward compatibility with older versions. +This function is deprecated; instead, use the object-oriented interface +described above. -You can also call parse_lines() to parse an array of lines or -parse_string_document() to parse a document already in memory. As with -parse_file(), parse_lines() and parse_string_document() default to sending -their output to C<STDOUT> unless changed with the output_fh() method. Be -aware that parse_lines() and parse_string_document() both expect raw bytes, -not decoded characters. +=over 4 + +=item pod2text([[-a,] [-NNN,]] INPUT[, OUTPUT]) + +Convert the POD source from INPUT to text and write it to OUTPUT. If OUTPUT +is not given, defaults to C<STDOUT>. INPUT can be any expression supported as +the second argument to two-argument open(). -To put the output from any parse method into a string instead of a file -handle, call the output_string() method instead of output_fh(). +If C<-a> is given as an initial argument, pass the C<alt> option to the +Pod::Text constructor. This enables alternative formatting. -See L<Pod::Simple> for more specific details on the methods available to -all derived parsers. +If C<-NNN> is given as an initial argument, pass the C<width> option to the +Pod::Text constructor with the number C<NNN> as its argument. This sets the +wrap line width to NNN. + +=back =head1 DIAGNOSTICS @@ -955,61 +1173,66 @@ option was set to C<die>. =back -=head1 BUGS +=head1 COMPATIBILITY -Encoding handling assumes that PerlIO is available and does not work -properly if it isn't. The C<utf8> option is therefore not supported -unless Perl is built with PerlIO support. +Pod::Text 2.03 (based on L<Pod::Parser>) was the first version of this module +included with Perl, in Perl 5.6.0. Earlier versions of Perl had a different +Pod::Text module, with a different API. -=head1 CAVEATS +The current API based on L<Pod::Simple> was added in Pod::Text 3.00. +Pod::Text 3.01 was included in Perl 5.9.3, the first version of Perl to +incorporate those changes. This is the first version that correctly supports +all modern POD syntax. The parse_from_filehandle() method was re-added for +backward compatibility in Pod::Text 3.07, included in Perl 5.9.4. -If Pod::Text is given the C<utf8> option, the encoding of its output file -handle will be forced to UTF-8 if possible, overriding any existing -encoding. This will be done even if the file handle is not created by -Pod::Text and was passed in from outside. This maintains consistency -regardless of PERL_UNICODE and other settings. +Pod::Text 3.12, included in Perl 5.10.1, first implemented the current +practice of attempting to match the default output encoding with the input +encoding of the POD source, unless overridden by the C<utf8> option or (added +later) the C<encoding> option. -If the C<utf8> option is not given, the encoding of its output file handle -will be forced to the detected encoding of the input POD, which preserves -whatever the input text is. This ensures backward compatibility with -earlier, pre-Unicode versions of this module, without large numbers of -Perl warnings. +Support for anchor text in LZ<><> links of type URL was added in Pod::Text +3.14, included in Perl 5.11.5. -This is not ideal, but it seems to be the best compromise. If it doesn't -work for you, please let me know the details of how it broke. +parse_lines(), parse_string_document(), and parse_file() set a default output +file handle of C<STDOUT> if one was not already set as of Pod::Text 3.18, +included in Perl 5.19.5. -=head1 NOTES +Pod::Text 4.00, included in Perl 5.23.7, aligned the module version and the +version of the podlators distribution. All modules included in podlators, and +the podlators distribution itself, share the same version number from this +point forward. -This is a replacement for an earlier Pod::Text module written by Tom -Christiansen. It has a revamped interface, since it now uses Pod::Simple, -but an interface roughly compatible with the old Pod::Text::pod2text() -function is still available. Please change to the new calling convention, -though. +Pod::Text 4.09, included in Perl 5.25.7, fixed a serious bug on EBCDIC +systems, present in all versions back to 3.00, that would cause opening +brackets to disappear. -The original Pod::Text contained code to do formatting via termcap -sequences, although it wasn't turned on by default and it was problematic to -get it to work at all. This rewrite doesn't even try to do that, but a -subclass of it does. Look for L<Pod::Text::Termcap>. +Pod::Text 5.00 now defaults, on non-EBCDIC systems, to UTF-8 encoding if it +sees a non-ASCII character in the input and the input encoding is not +specified. It also commits to an encoding with the first non-ASCII character +and does not change the output encoding if the input encoding changes. The +L<Encode> module is now used for all output encoding rather than PerlIO +layers, which fixes earlier problems with output to scalars. =head1 AUTHOR -Russ Allbery <rra@cpan.org>, based I<very> heavily on the original -Pod::Text by Tom Christiansen <tchrist@mox.perl.com> and its conversion to -Pod::Parser by Brad Appleton <bradapp@enteract.com>. Sean Burke's initial -conversion of Pod::Man to use Pod::Simple provided much-needed guidance on -how to use Pod::Simple. +Russ Allbery <rra@cpan.org>, based I<very> heavily on the original Pod::Text +by Tom Christiansen <tchrist@mox.perl.com> and its conversion to Pod::Parser +by Brad Appleton <bradapp@enteract.com>. Sean Burke's initial conversion of +Pod::Man to use Pod::Simple provided much-needed guidance on how to use +Pod::Simple. =head1 COPYRIGHT AND LICENSE -Copyright 1999-2002, 2004, 2006, 2008-2009, 2012-2016, 2018-2019 Russ Allbery -<rra@cpan.org> +Copyright 1999-2002, 2004, 2006, 2008-2009, 2012-2016, 2018-2019, 2022 Russ +Allbery <rra@cpan.org> This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO -L<Pod::Simple>, L<Pod::Text::Termcap>, L<perlpod(1)>, L<pod2text(1)> +L<Encode::Locale>, L<Encode::Supproted>, L<Pod::Simple>, +L<Pod::Text::Termcap>, L<perlpod(1)>, L<pod2text(1)> The current version of this module is always available from its web site at L<https://www.eyrie.org/~eagle/software/podlators/>. It is also part of the diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Color.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Color.pm index 5d47c5ecb3..2d656d6a3d 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Color.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Color.pm @@ -12,18 +12,15 @@ package Pod::Text::Color; -use 5.008; +use 5.010; use strict; use warnings; use Pod::Text (); use Term::ANSIColor qw(color colored); -use vars qw(@ISA $VERSION); - -@ISA = qw(Pod::Text); - -$VERSION = '4.14'; +our @ISA = qw(Pod::Text); +our $VERSION = '5.01'; ############################################################################## # Overrides @@ -170,11 +167,22 @@ options. Term::ANSIColor is used to get colors and therefore must be installed to use this module. -=head1 BUGS +=head1 COMPATIBILITY + +Pod::Text::Color 0.05 (based on L<Pod::Parser>) was the first version of this +module included with Perl, in Perl 5.6.0. + +The current API based on L<Pod::Simple> was added in Pod::Text::Color 2.00. +Pod::Text::Color 2.01 was included in Perl 5.9.3, the first version of Perl to +incorporate those changes. + +Several problems with wrapping and line length were fixed as recently as +Pod::Text::Color 4.11, included in Perl 5.29.1. -This is just a basic proof of concept. It should be seriously expanded to -support configurable coloration via options passed to the constructor, and -B<pod2text> should be taught about those. +This module inherits its API and most behavior from Pod::Text, so the details +in L<Pod::Text/COMPATIBILITY> also apply. Pod::Text and Pod::Text::Color have +had the same module version since 4.00, included in Perl 5.23.7. (They +unfortunately diverge in confusing ways prior to that.) =head1 AUTHOR @@ -182,7 +190,7 @@ Russ Allbery <rra@cpan.org>. =head1 COPYRIGHT AND LICENSE -Copyright 1999, 2001, 2004, 2006, 2008, 2009, 2018-2019 Russ Allbery +Copyright 1999, 2001, 2004, 2006, 2008, 2009, 2018-2019, 2022 Russ Allbery <rra@cpan.org> This program is free software; you may redistribute it and/or modify it diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Overstrike.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Overstrike.pm index 53bc6afef2..3135c8863c 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Overstrike.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Overstrike.pm @@ -19,17 +19,14 @@ package Pod::Text::Overstrike; -use 5.008; +use 5.010; use strict; use warnings; -use vars qw(@ISA $VERSION); - use Pod::Text (); -@ISA = qw(Pod::Text); - -$VERSION = '4.14'; +our @ISA = qw(Pod::Text); +our $VERSION = '5.01'; ############################################################################## # Overrides @@ -176,6 +173,22 @@ Currently, the outermost formatting instruction wins, so for example underlined text inside a region of bold text is displayed as simply bold. There may be some better approach possible. +=head1 COMPATIBILITY + +Pod::Text::Overstrike 1.01 (based on L<Pod::Parser>) was the first version of +this module included with Perl, in Perl 5.6.1. + +The current API based on L<Pod::Simple> was added in Pod::Text::Overstrike +2.00, included in Perl 5.9.3. + +Several problems with wrapping and line length were fixed as recently as +Pod::Text::Overstrike 2.04, included in Perl 5.11.5. + +This module inherits its API and most behavior from Pod::Text, so the details +in L<Pod::Text/COMPATIBILITY> also apply. Pod::Text and Pod::Text::Overstrike +have had the same module version since 4.00, included in Perl 5.23.7. (They +unfortunately diverge in confusing ways prior to that.) + =head1 AUTHOR Originally written by Joe Smith <Joe.Smith@inwap.com>, using the framework @@ -185,7 +198,7 @@ created by Russ Allbery <rra@cpan.org>. Subsequently updated by Russ Allbery. Copyright 2000 by Joe Smith <Joe.Smith@inwap.com> -Copyright 2001, 2004, 2008, 2014, 2018-2019 by Russ Allbery <rra@cpan.org> +Copyright 2001, 2004, 2008, 2014, 2018-2019, 2022 by Russ Allbery <rra@cpan.org> This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Termcap.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Termcap.pm index be218f0bf0..d4b74874d8 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Termcap.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Text/Termcap.pm @@ -12,7 +12,7 @@ package Pod::Text::Termcap; -use 5.008; +use 5.010; use strict; use warnings; @@ -20,11 +20,8 @@ use Pod::Text (); use POSIX (); use Term::Cap; -use vars qw(@ISA $VERSION); - -@ISA = qw(Pod::Text); - -$VERSION = '4.14'; +our @ISA = qw(Pod::Text); +our $VERSION = '5.01'; ############################################################################## # Overrides @@ -204,13 +201,13 @@ sub wrap { 1; __END__ +=for stopwords +ECMA-48 VT100 Allbery Solaris TERMPATH unformatted + =head1 NAME Pod::Text::Termcap - Convert POD data to ASCII text with format escapes -=for stopwords -ECMA-48 VT100 Allbery Solaris TERMPATH - =head1 SYNOPSIS use Pod::Text::Termcap; @@ -235,14 +232,37 @@ and how to override that behavior if necessary. If unable to find control strings for bold and underscore formatting, that formatting is skipped, resulting in the same output as Pod::Text. +=head1 COMPATIBILITY + +Pod::Text::Termcap 0.04 (based on L<Pod::Parser>) was the first version of +this module included with Perl, in Perl 5.6.0. + +The current API based on L<Pod::Simple> was added in Pod::Text::Termcap 2.00. +Pod::Text::Termcap 2.01 was included in Perl 5.9.3, the first version of Perl +to incorporate those changes. + +Several problems with wrapping and line length were fixed as recently as +Pod::Text::Termcap 4.11, included in Perl 5.29.1. + +Pod::Text::Termcap 4.13 stopped setting the TERMPATH environment variable +during module load. It also stopped falling back on VT100 escape sequences if +Term::Cap was not able to find usable escape sequences, instead producing +unformatted output for better results on dumb terminals. The next version to +be incorporated into Perl, 4.14, was included in Perl 5.31.8. + +This module inherits its API and most behavior from Pod::Text, so the details +in L<Pod::Text/COMPATIBILITY> also apply. Pod::Text and Pod::Text::Termcap +have had the same module version since 4.00, included in Perl 5.23.7. (They +unfortunately diverge in confusing ways prior to that.) + =head1 AUTHOR Russ Allbery <rra@cpan.org> =head1 COPYRIGHT AND LICENSE -Copyright 1999, 2001-2002, 2004, 2006, 2008-2009, 2014-2015, 2018-2019 Russ -Allbery <rra@cpan.org> +Copyright 1999, 2001-2002, 2004, 2006, 2008-2009, 2014-2015, 2018-2019, 2022 +Russ Allbery <rra@cpan.org> This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Usage.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Usage.pm index c290f2baf1..0ed3a60315 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Usage.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Pod/Usage.pm @@ -18,7 +18,7 @@ use Config; use Exporter; use File::Spec; -our $VERSION = '2.01'; +our $VERSION = '2.03'; our @EXPORT = qw(&pod2usage); our @ISA; |