Update Pod-Parser to CPAN version 1.62
authorChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Mon, 3 Feb 2014 21:41:24 +0000 (21:41 +0000)
committerChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Mon, 3 Feb 2014 22:04:55 +0000 (22:04 +0000)
  [DELTA]

 02-Feb-2014           Marek Rouchal                        <marekr@cpan.org>
 -----------------------------------------------------------------------------
 Version 1.62
 + CPAN#87891: More sanity checks in podselect()
   documentation patches by florent.angly@gmail.com, and a bit of stricter
   checking what clients pass to podselect()

Porting/Maintainers.pl
cpan/Pod-Parser/lib/Pod/Find.pm
cpan/Pod-Parser/lib/Pod/InputObjects.pm
cpan/Pod-Parser/lib/Pod/ParseUtils.pm
cpan/Pod-Parser/lib/Pod/Parser.pm
cpan/Pod-Parser/lib/Pod/PlainText.pm
cpan/Pod-Parser/lib/Pod/Select.pm
cpan/Pod-Parser/t/pod/testp2pt.pl

index 87821f6..42cdf5f 100755 (executable)
@@ -921,7 +921,7 @@ use File::Glob qw(:case);
     },
 
     'Pod::Parser' => {
-        'DISTRIBUTION' => 'MAREKR/Pod-Parser-1.61.tar.gz',
+        'DISTRIBUTION' => 'MAREKR/Pod-Parser-1.62.tar.gz',
         'FILES'        => q[cpan/Pod-Parser],
     },
 
index 1564aa3..6149e79 100644 (file)
-#############################################################################  \r
-# Pod/Find.pm -- finds files containing POD documentation\r
-#\r
-# Author: Marek Rouchal <marekr@cpan.org>\r
-# \r
-# Copyright (C) 1999-2000 by Marek Rouchal (and borrowing code\r
-# from Nick Ing-Simmon's PodToHtml). All rights reserved.\r
-# This file is part of "PodParser". Pod::Find is free software;\r
-# you can redistribute it and/or modify it under the same terms\r
-# as Perl itself.\r
-#############################################################################\r
-\r
-package Pod::Find;\r
-use strict;\r
-\r
-use vars qw($VERSION);\r
-$VERSION = '1.61';   ## Current version of this package\r
-require  5.005;   ## requires this Perl version or later\r
-use Carp;\r
-\r
-BEGIN {\r
-   if ($] < 5.006) {\r
-      require Symbol;\r
-      import Symbol;\r
-   }\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 NAME\r
-\r
-Pod::Find - find POD documents in directory trees\r
-\r
-=head1 SYNOPSIS\r
-\r
-  use Pod::Find qw(pod_find simplify_name);\r
-  my %pods = pod_find({ -verbose => 1, -inc => 1 });\r
-  foreach(keys %pods) {\r
-     print "found library POD `$pods{$_}' in $_\n";\r
-  }\r
-\r
-  print "podname=",simplify_name('a/b/c/mymodule.pod'),"\n";\r
-\r
-  $location = pod_where( { -inc => 1 }, "Pod::Find" );\r
-\r
-=head1 DESCRIPTION\r
-\r
-B<Pod::Find> provides a set of functions to locate POD files.  Note that\r
-no function is exported by default to avoid pollution of your namespace,\r
-so be sure to specify them in the B<use> statement if you need them:\r
-\r
-  use Pod::Find qw(pod_find);\r
-\r
-From this version on the typical SCM (software configuration management)\r
-files/directories like RCS, CVS, SCCS, .svn are ignored.\r
-\r
-=cut\r
-\r
-#use diagnostics;\r
-use Exporter;\r
-use File::Spec;\r
-use File::Find;\r
-use Cwd qw(abs_path cwd);\r
-\r
-use vars qw(@ISA @EXPORT_OK $VERSION);\r
-@ISA = qw(Exporter);\r
-@EXPORT_OK = qw(&pod_find &simplify_name &pod_where &contains_pod);\r
-\r
-# package global variables\r
-my $SIMPLIFY_RX;\r
-\r
-=head2 C<pod_find( { %opts } , @directories )>\r
-\r
-The function B<pod_find> searches for POD documents in a given set of\r
-files and/or directories. It returns a hash with the file names as keys\r
-and the POD name as value. The POD name is derived from the file name\r
-and its position in the directory tree.\r
-\r
-E.g. when searching in F<$HOME/perl5lib>, the file\r
-F<$HOME/perl5lib/MyModule.pm> would get the POD name I<MyModule>,\r
-whereas F<$HOME/perl5lib/Myclass/Subclass.pm> would be\r
-I<Myclass::Subclass>. The name information can be used for POD\r
-translators.\r
-\r
-Only text files containing at least one valid POD command are found.\r
-\r
-A warning is printed if more than one POD file with the same POD name\r
-is found, e.g. F<CPAN.pm> in different directories. This usually\r
-indicates duplicate occurrences of modules in the I<@INC> search path.\r
-\r
-B<OPTIONS> The first argument for B<pod_find> may be a hash reference\r
-with options. The rest are either directories that are searched\r
-recursively or files.  The POD names of files are the plain basenames\r
-with any Perl-like extension (.pm, .pl, .pod) stripped.\r
-\r
-=over 4\r
-\r
-=item C<-verbose =E<gt> 1>\r
-\r
-Print progress information while scanning.\r
-\r
-=item C<-perl =E<gt> 1>\r
-\r
-Apply Perl-specific heuristics to find the correct PODs. This includes\r
-stripping Perl-like extensions, omitting subdirectories that are numeric\r
-but do I<not> match the current Perl interpreter's version id, suppressing\r
-F<site_perl> as a module hierarchy name etc.\r
-\r
-=item C<-script =E<gt> 1>\r
-\r
-Search for PODs in the current Perl interpreter's installation \r
-B<scriptdir>. This is taken from the local L<Config|Config> module.\r
-\r
-=item C<-inc =E<gt> 1>\r
-\r
-Search for PODs in the current Perl interpreter's I<@INC> paths. This\r
-automatically considers paths specified in the C<PERL5LIB> environment\r
-as this is included in I<@INC> by the Perl interpreter itself.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-# return a hash of the POD files found\r
-# first argument may be a hashref (options),\r
-# rest is a list of directories to search recursively\r
-sub pod_find\r
-{\r
-    my %opts;\r
-    if(ref $_[0]) {\r
-        %opts = %{shift()};\r
-    }\r
-\r
-    $opts{-verbose} ||= 0;\r
-    $opts{-perl}    ||= 0;\r
-\r
-    my (@search) = @_;\r
-\r
-    if($opts{-script}) {\r
-        require Config;\r
-        push(@search, $Config::Config{scriptdir})\r
-            if -d $Config::Config{scriptdir};\r
-        $opts{-perl} = 1;\r
-    }\r
-\r
-    if($opts{-inc}) {\r
-        if ($^O eq 'MacOS') {\r
-            # tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS\r
-            my @new_INC = @INC;\r
-            for (@new_INC) {\r
-                if ( $_ eq '.' ) {\r
-                    $_ = ':';\r
-                } elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) {\r
-                    $_ = ':'. $_;\r
-                } else {\r
-                    $_ =~ s{^\./}{:};\r
-                }\r
-            }\r
-            push(@search, grep($_ ne File::Spec->curdir, @new_INC));\r
-        } else {\r
-            my %seen;\r
-            my $curdir = File::Spec->curdir;\r
-           foreach(@INC) {\r
-                next if $_ eq $curdir;\r
-               my $path = abs_path($_);\r
-                push(@search, $path) unless $seen{$path}++;\r
-            }\r
-        }\r
-\r
-        $opts{-perl} = 1;\r
-    }\r
-\r
-    if($opts{-perl}) {\r
-        require Config;\r
-        # this code simplifies the POD name for Perl modules:\r
-        # * remove "site_perl"\r
-        # * remove e.g. "i586-linux" (from 'archname')\r
-        # * remove e.g. 5.00503\r
-        # * remove pod/ if followed by *.pod (e.g. in pod/perlfunc.pod)\r
-\r
-        # Mac OS:\r
-        # * remove ":?site_perl:"\r
-        # * remove :?pod: if followed by *.pod (e.g. in :pod:perlfunc.pod)\r
-\r
-        if ($^O eq 'MacOS') {\r
-            $SIMPLIFY_RX =\r
-              qq!^(?i:\:?site_perl\:|\:?pod\:(?=.*?\\.pod\\z))*!;\r
-        } else {\r
-            $SIMPLIFY_RX =\r
-              qq!^(?i:site(_perl)?/|\Q$Config::Config{archname}\E/|\\d+\\.\\d+([_.]?\\d+)?/|pod/(?=.*?\\.pod\\z))*!;\r
-        }\r
-    }\r
-\r
-    my %dirs_visited;\r
-    my %pods;\r
-    my %names;\r
-    my $pwd = cwd();\r
-\r
-    foreach my $try (@search) {\r
-        unless(File::Spec->file_name_is_absolute($try)) {\r
-            # make path absolute\r
-            $try = File::Spec->catfile($pwd,$try);\r
-        }\r
-        # simplify path\r
-        # on VMS canonpath will vmsify:[the.path], but File::Find::find\r
-        # wants /unixy/paths\r
-        if ($^O eq 'VMS') {\r
-            $try = VMS::Filespec::unixify($try);\r
-        }\r
-        else {\r
-            $try = File::Spec->canonpath($try);\r
-        }\r
-        my $name;\r
-        if(-f $try) {\r
-            if($name = _check_and_extract_name($try, $opts{-verbose})) {\r
-                _check_for_duplicates($try, $name, \%names, \%pods);\r
-            }\r
-            next;\r
-        }\r
-        my $root_rx = $^O eq 'MacOS' ? qq!^\Q$try\E! : qq!^\Q$try\E/!;\r
-        $root_rx=~ s|//$|/|;  # remove trailing double slash\r
-        File::Find::find( sub {\r
-            my $item = $File::Find::name;\r
-            if(-d) {\r
-                if($item =~ m{/(?:RCS|CVS|SCCS|\.svn)$}) {\r
-                    $File::Find::prune = 1;\r
-                    return;\r
-                }\r
-                elsif($dirs_visited{$item}) {\r
-                    warn "Directory '$item' already seen, skipping.\n"\r
-                        if($opts{-verbose});\r
-                    $File::Find::prune = 1;\r
-                    return;\r
-                }\r
-                else {\r
-                    $dirs_visited{$item} = 1;\r
-                }\r
-                if($opts{-perl} && /^(\d+\.[\d_]+)\z/s && eval "$1" != $]) {\r
-                    $File::Find::prune = 1;\r
-                    warn "Perl $] version mismatch on $_, skipping.\n"\r
-                        if($opts{-verbose});\r
-                }\r
-                return;\r
-            }\r
-            if($name = _check_and_extract_name($item, $opts{-verbose}, $root_rx)) {\r
-                _check_for_duplicates($item, $name, \%names, \%pods);\r
-            }\r
-        }, $try); # end of File::Find::find\r
-    }\r
-    chdir $pwd;\r
-    return %pods;\r
-}\r
-\r
-sub _check_for_duplicates {\r
-    my ($file, $name, $names_ref, $pods_ref) = @_;\r
-    if($$names_ref{$name}) {\r
-        warn "Duplicate POD found (shadowing?): $name ($file)\n";\r
-        warn '    Already seen in ',\r
-            join(' ', grep($$pods_ref{$_} eq $name, keys %$pods_ref)),"\n";\r
-    }\r
-    else {\r
-        $$names_ref{$name} = 1;\r
-    }\r
-    return $$pods_ref{$file} = $name;\r
-}\r
-\r
-sub _check_and_extract_name {\r
-    my ($file, $verbose, $root_rx) = @_;\r
-\r
-    # check extension or executable flag\r
-    # this involves testing the .bat extension on Win32!\r
-    unless(-f $file && -T $file && ($file =~ /\.(pod|pm|plx?)\z/i || -x $file )) {\r
-      return;\r
-    }\r
-\r
-    return unless contains_pod($file,$verbose);\r
-\r
-    # strip non-significant path components\r
-    # TODO what happens on e.g. Win32?\r
-    my $name = $file;\r
-    if(defined $root_rx) {\r
-        $name =~ s/$root_rx//is;\r
-        $name =~ s/$SIMPLIFY_RX//is if(defined $SIMPLIFY_RX);\r
-    }\r
-    else {\r
-        if ($^O eq 'MacOS') {\r
-            $name =~ s/^.*://s;\r
-        } else {\r
-            $name =~ s{^.*/}{}s;\r
-        }\r
-    }\r
-    _simplify($name);\r
-    $name =~ s{/+}{::}g;\r
-    if ($^O eq 'MacOS') {\r
-        $name =~ s{:+}{::}g; # : -> ::\r
-    } else {\r
-        $name =~ s{/+}{::}g; # / -> ::\r
-    }\r
-    return $name;\r
-}\r
-\r
-=head2 C<simplify_name( $str )>\r
-\r
-The function B<simplify_name> is equivalent to B<basename>, but also\r
-strips Perl-like extensions (.pm, .pl, .pod) and extensions like\r
-F<.bat>, F<.cmd> on Win32 and OS/2, or F<.com> on VMS, respectively.\r
-\r
-=cut\r
-\r
-# basic simplification of the POD name:\r
-# basename & strip extension\r
-sub simplify_name {\r
-    my ($str) = @_;\r
-    # remove all path components\r
-    if ($^O eq 'MacOS') {\r
-        $str =~ s/^.*://s;\r
-    } else {\r
-        $str =~ s{^.*/}{}s;\r
-    }\r
-    _simplify($str);\r
-    return $str;\r
-}\r
-\r
-# internal sub only\r
-sub _simplify {\r
-    # strip Perl's own extensions\r
-    $_[0] =~ s/\.(pod|pm|plx?)\z//i;\r
-    # strip meaningless extensions on Win32 and OS/2\r
-    $_[0] =~ s/\.(bat|exe|cmd)\z//i if($^O =~ /mswin|os2/i);\r
-    # strip meaningless extensions on VMS\r
-    $_[0] =~ s/\.(com)\z//i if($^O eq 'VMS');\r
-}\r
-\r
-# contribution from Tim Jenness <t.jenness@jach.hawaii.edu>\r
-\r
-=head2 C<pod_where( { %opts }, $pod )>\r
-\r
-Returns the location of a pod document given a search directory\r
-and a module (e.g. C<File::Find>) or script (e.g. C<perldoc>) name.\r
-\r
-Options:\r
-\r
-=over 4\r
-\r
-=item C<-inc =E<gt> 1>\r
-\r
-Search @INC for the pod and also the C<scriptdir> defined in the\r
-L<Config|Config> module.\r
-\r
-=item C<-dirs =E<gt> [ $dir1, $dir2, ... ]>\r
-\r
-Reference to an array of search directories. These are searched in order\r
-before looking in C<@INC> (if B<-inc>). Current directory is used if\r
-none are specified.\r
-\r
-=item C<-verbose =E<gt> 1>\r
-\r
-List directories as they are searched\r
-\r
-=back\r
-\r
-Returns the full path of the first occurrence to the file.\r
-Package names (eg 'A::B') are automatically converted to directory\r
-names in the selected directory. (eg on unix 'A::B' is converted to\r
-'A/B'). Additionally, '.pm', '.pl' and '.pod' are appended to the\r
-search automatically if required.\r
-\r
-A subdirectory F<pod/> is also checked if it exists in any of the given\r
-search directories. This ensures that e.g. L<perlfunc|perlfunc> is\r
-found.\r
-\r
-It is assumed that if a module name is supplied, that that name\r
-matches the file name. Pods are not opened to check for the 'NAME'\r
-entry.\r
-\r
-A check is made to make sure that the file that is found does \r
-contain some pod documentation.\r
-\r
-=cut\r
-\r
-sub pod_where {\r
-\r
-  # default options\r
-  my %options = (\r
-         '-inc' => 0,\r
-         '-verbose' => 0,\r
-         '-dirs' => [ File::Spec->curdir ],\r
-        );\r
-\r
-  # Check for an options hash as first argument\r
-  if (defined $_[0] && ref($_[0]) eq 'HASH') {\r
-    my $opt = shift;\r
-\r
-    # Merge default options with supplied options\r
-    %options = (%options, %$opt);\r
-  }\r
-\r
-  # Check usage\r
-  carp 'Usage: pod_where({options}, $pod)' unless (scalar(@_));\r
-\r
-  # Read argument\r
-  my $pod = shift;\r
-\r
-  # Split on :: and then join the name together using File::Spec\r
-  my @parts = split (/::/, $pod);\r
-\r
-  # Get full directory list\r
-  my @search_dirs = @{ $options{'-dirs'} };\r
-\r
-  if ($options{'-inc'}) {\r
-\r
-    require Config;\r
-\r
-    # Add @INC\r
-    if ($^O eq 'MacOS' && $options{'-inc'}) {\r
-        # tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS\r
-        my @new_INC = @INC;\r
-        for (@new_INC) {\r
-            if ( $_ eq '.' ) {\r
-                $_ = ':';\r
-            } elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) {\r
-                $_ = ':'. $_;\r
-            } else {\r
-                $_ =~ s{^\./}{:};\r
-            }\r
-        }\r
-        push (@search_dirs, @new_INC);\r
-    } elsif ($options{'-inc'}) {\r
-        push (@search_dirs, @INC);\r
-    }\r
-\r
-    # Add location of pod documentation for perl man pages (eg perlfunc)\r
-    # This is a pod directory in the private install tree\r
-    #my $perlpoddir = File::Spec->catdir($Config::Config{'installprivlib'},\r
-    #                                  'pod');\r
-    #push (@search_dirs, $perlpoddir)\r
-    #  if -d $perlpoddir;\r
-\r
-    # Add location of binaries such as pod2text\r
-    push (@search_dirs, $Config::Config{'scriptdir'})\r
-      if -d $Config::Config{'scriptdir'};\r
-  }\r
-\r
-  warn 'Search path is: '.join(' ', @search_dirs)."\n"\r
-        if $options{'-verbose'};\r
-\r
-  # Loop over directories\r
-  Dir: foreach my $dir ( @search_dirs ) {\r
-\r
-    # Don't bother if can't find the directory\r
-    if (-d $dir) {\r
-      warn "Looking in directory $dir\n"\r
-        if $options{'-verbose'};\r
-\r
-      # Now concatenate this directory with the pod we are searching for\r
-      my $fullname = File::Spec->catfile($dir, @parts);\r
-      $fullname = VMS::Filespec::unixify($fullname) if $^O eq 'VMS';\r
-      warn "Filename is now $fullname\n"\r
-        if $options{'-verbose'};\r
-\r
-      # Loop over possible extensions\r
-      foreach my $ext ('', '.pod', '.pm', '.pl') {\r
-        my $fullext = $fullname . $ext;\r
-        if (-f $fullext &&\r
-         contains_pod($fullext, $options{'-verbose'}) ) {\r
-          warn "FOUND: $fullext\n" if $options{'-verbose'};\r
-          return $fullext;\r
-        }\r
-      }\r
-    } else {\r
-      warn "Directory $dir does not exist\n"\r
-        if $options{'-verbose'};\r
-      next Dir;\r
-    }\r
-    # for some strange reason the path on MacOS/darwin/cygwin is\r
-    # 'pods' not 'pod'\r
-    # this could be the case also for other systems that\r
-    # have a case-tolerant file system, but File::Spec\r
-    # does not recognize 'darwin' yet. And cygwin also has "pods",\r
-    # but is not case tolerant. Oh well...\r
-    if((File::Spec->case_tolerant || $^O =~ /macos|darwin|cygwin/i)\r
-     && -d File::Spec->catdir($dir,'pods')) {\r
-      $dir = File::Spec->catdir($dir,'pods');\r
-      redo Dir;\r
-    }\r
-    if(-d File::Spec->catdir($dir,'pod')) {\r
-      $dir = File::Spec->catdir($dir,'pod');\r
-      redo Dir;\r
-    }\r
-  }\r
-  # No match;\r
-  return;\r
-}\r
-\r
-=head2 C<contains_pod( $file , $verbose )>\r
-\r
-Returns true if the supplied filename (not POD module) contains some pod\r
-information.\r
-\r
-=cut\r
-\r
-sub contains_pod {\r
-  my $file = shift;\r
-  my $verbose = 0;\r
-  $verbose = shift if @_;\r
-\r
-  # check for one line of POD\r
-  my $podfh;\r
-  if ($] < 5.006) {\r
-    $podfh = gensym();\r
-  }\r
-\r
-  unless(open($podfh,"<$file")) {\r
-    warn "Error: $file is unreadable: $!\n";\r
-    return;\r
-  }\r
-  \r
-  local $/ = undef;\r
-  my $pod = <$podfh>;\r
-  close($podfh) || die "Error closing $file: $!\n";\r
-  unless($pod =~ /^=(head\d|pod|over|item|cut)\b/m) {\r
-    warn "No POD in $file, skipping.\n"\r
-      if($verbose);\r
-    return 0;\r
-  }\r
-\r
-  return 1;\r
-}\r
-\r
-=head1 AUTHOR\r
-\r
-Please report bugs using L<http://rt.cpan.org>.\r
-\r
-Marek Rouchal E<lt>marekr@cpan.orgE<gt>,\r
-heavily borrowing code from Nick Ing-Simmons' PodToHtml.\r
-\r
-Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> provided\r
-C<pod_where> and C<contains_pod>.\r
-\r
-B<Pod::Find> is part of the L<Pod::Parser> distribution.\r
-\r
-=head1 SEE ALSO\r
-\r
-L<Pod::Parser>, L<Pod::Checker>, L<perldoc>\r
-\r
-=cut\r
-\r
-1;\r
-\r
+#############################################################################  
+# Pod/Find.pm -- finds files containing POD documentation
+#
+# Author: Marek Rouchal <marekr@cpan.org>
+# 
+# Copyright (C) 1999-2000 by Marek Rouchal (and borrowing code
+# from Nick Ing-Simmon's PodToHtml). All rights reserved.
+# This file is part of "PodParser". Pod::Find is free software;
+# you can redistribute it and/or modify it under the same terms
+# as Perl itself.
+#############################################################################
+
+package Pod::Find;
+use strict;
+
+use vars qw($VERSION);
+$VERSION = '1.62';   ## Current version of this package
+require  5.005;   ## requires this Perl version or later
+use Carp;
+
+BEGIN {
+   if ($] < 5.006) {
+      require Symbol;
+      import Symbol;
+   }
+}
+
+#############################################################################
+
+=head1 NAME
+
+Pod::Find - find POD documents in directory trees
+
+=head1 SYNOPSIS
+
+  use Pod::Find qw(pod_find simplify_name);
+  my %pods = pod_find({ -verbose => 1, -inc => 1 });
+  foreach(keys %pods) {
+     print "found library POD `$pods{$_}' in $_\n";
+  }
+
+  print "podname=",simplify_name('a/b/c/mymodule.pod'),"\n";
+
+  $location = pod_where( { -inc => 1 }, "Pod::Find" );
+
+=head1 DESCRIPTION
+
+B<NOTE: This module is considered legacy; modern Perl releases (5.18 and
+higher) are going to remove Pod-Parser from core and use L<Pod-Simple>
+for all things POD.>
+
+B<Pod::Find> provides a set of functions to locate POD files.  Note that
+no function is exported by default to avoid pollution of your namespace,
+so be sure to specify them in the B<use> statement if you need them:
+
+  use Pod::Find qw(pod_find);
+
+From this version on the typical SCM (software configuration management)
+files/directories like RCS, CVS, SCCS, .svn are ignored.
+
+=cut
+
+#use diagnostics;
+use Exporter;
+use File::Spec;
+use File::Find;
+use Cwd qw(abs_path cwd);
+
+use vars qw(@ISA @EXPORT_OK $VERSION);
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(&pod_find &simplify_name &pod_where &contains_pod);
+
+# package global variables
+my $SIMPLIFY_RX;
+
+=head2 C<pod_find( { %opts } , @directories )>
+
+The function B<pod_find> searches for POD documents in a given set of
+files and/or directories. It returns a hash with the file names as keys
+and the POD name as value. The POD name is derived from the file name
+and its position in the directory tree.
+
+E.g. when searching in F<$HOME/perl5lib>, the file
+F<$HOME/perl5lib/MyModule.pm> would get the POD name I<MyModule>,
+whereas F<$HOME/perl5lib/Myclass/Subclass.pm> would be
+I<Myclass::Subclass>. The name information can be used for POD
+translators.
+
+Only text files containing at least one valid POD command are found.
+
+A warning is printed if more than one POD file with the same POD name
+is found, e.g. F<CPAN.pm> in different directories. This usually
+indicates duplicate occurrences of modules in the I<@INC> search path.
+
+B<OPTIONS> The first argument for B<pod_find> may be a hash reference
+with options. The rest are either directories that are searched
+recursively or files.  The POD names of files are the plain basenames
+with any Perl-like extension (.pm, .pl, .pod) stripped.
+
+=over 4
+
+=item C<-verbose =E<gt> 1>
+
+Print progress information while scanning.
+
+=item C<-perl =E<gt> 1>
+
+Apply Perl-specific heuristics to find the correct PODs. This includes
+stripping Perl-like extensions, omitting subdirectories that are numeric
+but do I<not> match the current Perl interpreter's version id, suppressing
+F<site_perl> as a module hierarchy name etc.
+
+=item C<-script =E<gt> 1>
+
+Search for PODs in the current Perl interpreter's installation 
+B<scriptdir>. This is taken from the local L<Config|Config> module.
+
+=item C<-inc =E<gt> 1>
+
+Search for PODs in the current Perl interpreter's I<@INC> paths. This
+automatically considers paths specified in the C<PERL5LIB> environment
+as this is included in I<@INC> by the Perl interpreter itself.
+
+=back
+
+=cut
+
+# return a hash of the POD files found
+# first argument may be a hashref (options),
+# rest is a list of directories to search recursively
+sub pod_find
+{
+    my %opts;
+    if(ref $_[0]) {
+        %opts = %{shift()};
+    }
+
+    $opts{-verbose} ||= 0;
+    $opts{-perl}    ||= 0;
+
+    my (@search) = @_;
+
+    if($opts{-script}) {
+        require Config;
+        push(@search, $Config::Config{scriptdir})
+            if -d $Config::Config{scriptdir};
+        $opts{-perl} = 1;
+    }
+
+    if($opts{-inc}) {
+        if ($^O eq 'MacOS') {
+            # tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS
+            my @new_INC = @INC;
+            for (@new_INC) {
+                if ( $_ eq '.' ) {
+                    $_ = ':';
+                } elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) {
+                    $_ = ':'. $_;
+                } else {
+                    $_ =~ s{^\./}{:};
+                }
+            }
+            push(@search, grep($_ ne File::Spec->curdir, @new_INC));
+        } else {
+            my %seen;
+            my $curdir = File::Spec->curdir;
+           foreach(@INC) {
+                next if $_ eq $curdir;
+               my $path = abs_path($_);
+                push(@search, $path) unless $seen{$path}++;
+            }
+        }
+
+        $opts{-perl} = 1;
+    }
+
+    if($opts{-perl}) {
+        require Config;
+        # this code simplifies the POD name for Perl modules:
+        # * remove "site_perl"
+        # * remove e.g. "i586-linux" (from 'archname')
+        # * remove e.g. 5.00503
+        # * remove pod/ if followed by *.pod (e.g. in pod/perlfunc.pod)
+
+        # Mac OS:
+        # * remove ":?site_perl:"
+        # * remove :?pod: if followed by *.pod (e.g. in :pod:perlfunc.pod)
+
+        if ($^O eq 'MacOS') {
+            $SIMPLIFY_RX =
+              qq!^(?i:\:?site_perl\:|\:?pod\:(?=.*?\\.pod\\z))*!;
+        } else {
+            $SIMPLIFY_RX =
+              qq!^(?i:site(_perl)?/|\Q$Config::Config{archname}\E/|\\d+\\.\\d+([_.]?\\d+)?/|pod/(?=.*?\\.pod\\z))*!;
+        }
+    }
+
+    my %dirs_visited;
+    my %pods;
+    my %names;
+    my $pwd = cwd();
+
+    foreach my $try (@search) {
+        unless(File::Spec->file_name_is_absolute($try)) {
+            # make path absolute
+            $try = File::Spec->catfile($pwd,$try);
+        }
+        # simplify path
+        # on VMS canonpath will vmsify:[the.path], but File::Find::find
+        # wants /unixy/paths
+        if ($^O eq 'VMS') {
+            $try = VMS::Filespec::unixify($try);
+        }
+        else {
+            $try = File::Spec->canonpath($try);
+        }
+        my $name;
+        if(-f $try) {
+            if($name = _check_and_extract_name($try, $opts{-verbose})) {
+                _check_for_duplicates($try, $name, \%names, \%pods);
+            }
+            next;
+        }
+        my $root_rx = $^O eq 'MacOS' ? qq!^\Q$try\E! : qq!^\Q$try\E/!;
+        $root_rx=~ s|//$|/|;  # remove trailing double slash
+        File::Find::find( sub {
+            my $item = $File::Find::name;
+            if(-d) {
+                if($item =~ m{/(?:RCS|CVS|SCCS|\.svn)$}) {
+                    $File::Find::prune = 1;
+                    return;
+                }
+                elsif($dirs_visited{$item}) {
+                    warn "Directory '$item' already seen, skipping.\n"
+                        if($opts{-verbose});
+                    $File::Find::prune = 1;
+                    return;
+                }
+                else {
+                    $dirs_visited{$item} = 1;
+                }
+                if($opts{-perl} && /^(\d+\.[\d_]+)\z/s && eval "$1" != $]) {
+                    $File::Find::prune = 1;
+                    warn "Perl $] version mismatch on $_, skipping.\n"
+                        if($opts{-verbose});
+                }
+                return;
+            }
+            if($name = _check_and_extract_name($item, $opts{-verbose}, $root_rx)) {
+                _check_for_duplicates($item, $name, \%names, \%pods);
+            }
+        }, $try); # end of File::Find::find
+    }
+    chdir $pwd;
+    return %pods;
+}
+
+sub _check_for_duplicates {
+    my ($file, $name, $names_ref, $pods_ref) = @_;
+    if($$names_ref{$name}) {
+        warn "Duplicate POD found (shadowing?): $name ($file)\n";
+        warn '    Already seen in ',
+            join(' ', grep($$pods_ref{$_} eq $name, keys %$pods_ref)),"\n";
+    }
+    else {
+        $$names_ref{$name} = 1;
+    }
+    return $$pods_ref{$file} = $name;
+}
+
+sub _check_and_extract_name {
+    my ($file, $verbose, $root_rx) = @_;
+
+    # check extension or executable flag
+    # this involves testing the .bat extension on Win32!
+    unless(-f $file && -T $file && ($file =~ /\.(pod|pm|plx?)\z/i || -x $file )) {
+      return;
+    }
+
+    return unless contains_pod($file,$verbose);
+
+    # strip non-significant path components
+    # TODO what happens on e.g. Win32?
+    my $name = $file;
+    if(defined $root_rx) {
+        $name =~ s/$root_rx//is;
+        $name =~ s/$SIMPLIFY_RX//is if(defined $SIMPLIFY_RX);
+    }
+    else {
+        if ($^O eq 'MacOS') {
+            $name =~ s/^.*://s;
+        } else {
+            $name =~ s{^.*/}{}s;
+        }
+    }
+    _simplify($name);
+    $name =~ s{/+}{::}g;
+    if ($^O eq 'MacOS') {
+        $name =~ s{:+}{::}g; # : -> ::
+    } else {
+        $name =~ s{/+}{::}g; # / -> ::
+    }
+    return $name;
+}
+
+=head2 C<simplify_name( $str )>
+
+The function B<simplify_name> is equivalent to B<basename>, but also
+strips Perl-like extensions (.pm, .pl, .pod) and extensions like
+F<.bat>, F<.cmd> on Win32 and OS/2, or F<.com> on VMS, respectively.
+
+=cut
+
+# basic simplification of the POD name:
+# basename & strip extension
+sub simplify_name {
+    my ($str) = @_;
+    # remove all path components
+    if ($^O eq 'MacOS') {
+        $str =~ s/^.*://s;
+    } else {
+        $str =~ s{^.*/}{}s;
+    }
+    _simplify($str);
+    return $str;
+}
+
+# internal sub only
+sub _simplify {
+    # strip Perl's own extensions
+    $_[0] =~ s/\.(pod|pm|plx?)\z//i;
+    # strip meaningless extensions on Win32 and OS/2
+    $_[0] =~ s/\.(bat|exe|cmd)\z//i if($^O =~ /mswin|os2/i);
+    # strip meaningless extensions on VMS
+    $_[0] =~ s/\.(com)\z//i if($^O eq 'VMS');
+}
+
+# contribution from Tim Jenness <t.jenness@jach.hawaii.edu>
+
+=head2 C<pod_where( { %opts }, $pod )>
+
+Returns the location of a pod document given a search directory
+and a module (e.g. C<File::Find>) or script (e.g. C<perldoc>) name.
+
+Options:
+
+=over 4
+
+=item C<-inc =E<gt> 1>
+
+Search @INC for the pod and also the C<scriptdir> defined in the
+L<Config|Config> module.
+
+=item C<-dirs =E<gt> [ $dir1, $dir2, ... ]>
+
+Reference to an array of search directories. These are searched in order
+before looking in C<@INC> (if B<-inc>). Current directory is used if
+none are specified.
+
+=item C<-verbose =E<gt> 1>
+
+List directories as they are searched
+
+=back
+
+Returns the full path of the first occurrence to the file.
+Package names (eg 'A::B') are automatically converted to directory
+names in the selected directory. (eg on unix 'A::B' is converted to
+'A/B'). Additionally, '.pm', '.pl' and '.pod' are appended to the
+search automatically if required.
+
+A subdirectory F<pod/> is also checked if it exists in any of the given
+search directories. This ensures that e.g. L<perlfunc|perlfunc> is
+found.
+
+It is assumed that if a module name is supplied, that that name
+matches the file name. Pods are not opened to check for the 'NAME'
+entry.
+
+A check is made to make sure that the file that is found does 
+contain some pod documentation.
+
+=cut
+
+sub pod_where {
+
+  # default options
+  my %options = (
+         '-inc' => 0,
+         '-verbose' => 0,
+         '-dirs' => [ File::Spec->curdir ],
+        );
+
+  # Check for an options hash as first argument
+  if (defined $_[0] && ref($_[0]) eq 'HASH') {
+    my $opt = shift;
+
+    # Merge default options with supplied options
+    %options = (%options, %$opt);
+  }
+
+  # Check usage
+  carp 'Usage: pod_where({options}, $pod)' unless (scalar(@_));
+
+  # Read argument
+  my $pod = shift;
+
+  # Split on :: and then join the name together using File::Spec
+  my @parts = split (/::/, $pod);
+
+  # Get full directory list
+  my @search_dirs = @{ $options{'-dirs'} };
+
+  if ($options{'-inc'}) {
+
+    require Config;
+
+    # Add @INC
+    if ($^O eq 'MacOS' && $options{'-inc'}) {
+        # tolerate '.', './some_dir' and '(../)+some_dir' on Mac OS
+        my @new_INC = @INC;
+        for (@new_INC) {
+            if ( $_ eq '.' ) {
+                $_ = ':';
+            } elsif ( $_ =~ s{^((?:\.\./)+)}{':' x (length($1)/3)}e ) {
+                $_ = ':'. $_;
+            } else {
+                $_ =~ s{^\./}{:};
+            }
+        }
+        push (@search_dirs, @new_INC);
+    } elsif ($options{'-inc'}) {
+        push (@search_dirs, @INC);
+    }
+
+    # Add location of pod documentation for perl man pages (eg perlfunc)
+    # This is a pod directory in the private install tree
+    #my $perlpoddir = File::Spec->catdir($Config::Config{'installprivlib'},
+    #                                  'pod');
+    #push (@search_dirs, $perlpoddir)
+    #  if -d $perlpoddir;
+
+    # Add location of binaries such as pod2text
+    push (@search_dirs, $Config::Config{'scriptdir'})
+      if -d $Config::Config{'scriptdir'};
+  }
+
+  warn 'Search path is: '.join(' ', @search_dirs)."\n"
+        if $options{'-verbose'};
+
+  # Loop over directories
+  Dir: foreach my $dir ( @search_dirs ) {
+
+    # Don't bother if can't find the directory
+    if (-d $dir) {
+      warn "Looking in directory $dir\n"
+        if $options{'-verbose'};
+
+      # Now concatenate this directory with the pod we are searching for
+      my $fullname = File::Spec->catfile($dir, @parts);
+      $fullname = VMS::Filespec::unixify($fullname) if $^O eq 'VMS';
+      warn "Filename is now $fullname\n"
+        if $options{'-verbose'};
+
+      # Loop over possible extensions
+      foreach my $ext ('', '.pod', '.pm', '.pl') {
+        my $fullext = $fullname . $ext;
+        if (-f $fullext &&
+         contains_pod($fullext, $options{'-verbose'}) ) {
+          warn "FOUND: $fullext\n" if $options{'-verbose'};
+          return $fullext;
+        }
+      }
+    } else {
+      warn "Directory $dir does not exist\n"
+        if $options{'-verbose'};
+      next Dir;
+    }
+    # for some strange reason the path on MacOS/darwin/cygwin is
+    # 'pods' not 'pod'
+    # this could be the case also for other systems that
+    # have a case-tolerant file system, but File::Spec
+    # does not recognize 'darwin' yet. And cygwin also has "pods",
+    # but is not case tolerant. Oh well...
+    if((File::Spec->case_tolerant || $^O =~ /macos|darwin|cygwin/i)
+     && -d File::Spec->catdir($dir,'pods')) {
+      $dir = File::Spec->catdir($dir,'pods');
+      redo Dir;
+    }
+    if(-d File::Spec->catdir($dir,'pod')) {
+      $dir = File::Spec->catdir($dir,'pod');
+      redo Dir;
+    }
+  }
+  # No match;
+  return;
+}
+
+=head2 C<contains_pod( $file , $verbose )>
+
+Returns true if the supplied filename (not POD module) contains some pod
+information.
+
+=cut
+
+sub contains_pod {
+  my $file = shift;
+  my $verbose = 0;
+  $verbose = shift if @_;
+
+  # check for one line of POD
+  my $podfh;
+  if ($] < 5.006) {
+    $podfh = gensym();
+  }
+
+  unless(open($podfh,"<$file")) {
+    warn "Error: $file is unreadable: $!\n";
+    return;
+  }
+  
+  local $/ = undef;
+  my $pod = <$podfh>;
+  close($podfh) || die "Error closing $file: $!\n";
+  unless($pod =~ /^=(head\d|pod|over|item|cut)\b/m) {
+    warn "No POD in $file, skipping.\n"
+      if($verbose);
+    return 0;
+  }
+
+  return 1;
+}
+
+=head1 AUTHOR
+
+Please report bugs using L<http://rt.cpan.org>.
+
+Marek Rouchal E<lt>marekr@cpan.orgE<gt>,
+heavily borrowing code from Nick Ing-Simmons' PodToHtml.
+
+Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> provided
+C<pod_where> and C<contains_pod>.
+
+B<Pod::Find> is part of the L<Pod::Parser> distribution.
+
+=head1 SEE ALSO
+
+L<Pod::Parser>, L<Pod::Checker>, L<perldoc>
+
+=cut
+
+1;
+
index dd078e6..87ce247 100644 (file)
-#############################################################################\r
-# Pod/InputObjects.pm -- package which defines objects for input streams\r
-# and paragraphs and commands when parsing POD docs.\r
-#\r
-# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.\r
-# This file is part of "PodParser". PodParser is free software;\r
-# you can redistribute it and/or modify it under the same terms\r
-# as Perl itself.\r
-#############################################################################\r
-\r
-package Pod::InputObjects;\r
-use strict;\r
-\r
-use vars qw($VERSION);\r
-$VERSION = '1.61';  ## Current version of this package\r
-require  5.005;    ## requires this Perl version or later\r
-\r
-#############################################################################\r
-\r
-=head1 NAME\r
-\r
-Pod::InputObjects - objects representing POD input paragraphs, commands, etc.\r
-\r
-=head1 SYNOPSIS\r
-\r
-    use Pod::InputObjects;\r
-\r
-=head1 REQUIRES\r
-\r
-perl5.004, Carp\r
-\r
-=head1 EXPORTS\r
-\r
-Nothing.\r
-\r
-=head1 DESCRIPTION\r
-\r
-This module defines some basic input objects used by B<Pod::Parser> when\r
-reading and parsing POD text from an input source. The following objects\r
-are defined:\r
-\r
-=begin __PRIVATE__\r
-\r
-=over 4\r
-\r
-=item package B<Pod::InputSource>\r
-\r
-An object corresponding to a source of POD input text. It is mostly a\r
-wrapper around a filehandle or C<IO::Handle>-type object (or anything\r
-that implements the C<getline()> method) which keeps track of some\r
-additional information relevant to the parsing of PODs.\r
-\r
-=back\r
-\r
-=end __PRIVATE__\r
-\r
-=over 4\r
-\r
-=item package B<Pod::Paragraph>\r
-\r
-An object corresponding to a paragraph of POD input text. It may be a\r
-plain paragraph, a verbatim paragraph, or a command paragraph (see\r
-L<perlpod>).\r
-\r
-=item package B<Pod::InteriorSequence>\r
-\r
-An object corresponding to an interior sequence command from the POD\r
-input text (see L<perlpod>).\r
-\r
-=item package B<Pod::ParseTree>\r
-\r
-An object corresponding to a tree of parsed POD text. Each "node" in\r
-a parse-tree (or I<ptree>) is either a text-string or a reference to\r
-a B<Pod::InteriorSequence> object. The nodes appear in the parse-tree\r
-in the order in which they were parsed from left-to-right.\r
-\r
-=back\r
-\r
-Each of these input objects are described in further detail in the\r
-sections which follow.\r
-\r
-=cut\r
-\r
-#############################################################################\r
-\r
-package Pod::InputSource;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head1 B<Pod::InputSource>\r
-\r
-This object corresponds to an input source or stream of POD\r
-documentation. When parsing PODs, it is necessary to associate and store\r
-certain context information with each input source. All of this\r
-information is kept together with the stream itself in one of these\r
-C<Pod::InputSource> objects. Each such object is merely a wrapper around\r
-an C<IO::Handle> object of some kind (or at least something that\r
-implements the C<getline()> method). They have the following\r
-methods/attributes:\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head2 B<new()>\r
-\r
-        my $pod_input1 = Pod::InputSource->new(-handle => $filehandle);\r
-        my $pod_input2 = new Pod::InputSource(-handle => $filehandle,\r
-                                              -name   => $name);\r
-        my $pod_input3 = new Pod::InputSource(-handle => \*STDIN);\r
-        my $pod_input4 = Pod::InputSource->new(-handle => \*STDIN,\r
-                                               -name => "(STDIN)");\r
-\r
-This is a class method that constructs a C<Pod::InputSource> object and\r
-returns a reference to the new input source object. It takes one or more\r
-keyword arguments in the form of a hash. The keyword C<-handle> is\r
-required and designates the corresponding input handle. The keyword\r
-C<-name> is optional and specifies the name associated with the input\r
-handle (typically a file name).\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub new {\r
-    ## Determine if we were called via an object-ref or a classname\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-\r
-    ## Any remaining arguments are treated as initial values for the\r
-    ## hash that is used to represent this object. Note that we default\r
-    ## certain values by specifying them *before* the arguments passed.\r
-    ## If they are in the argument list, they will override the defaults.\r
-    my $self = { -name        => '(unknown)',\r
-                 -handle      => undef,\r
-                 -was_cutting => 0,\r
-                 @_ };\r
-\r
-    ## Bless ourselves into the desired class and perform any initialization\r
-    bless $self, $class;\r
-    return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head2 B<name()>\r
-\r
-        my $filename = $pod_input->name();\r
-        $pod_input->name($new_filename_to_use);\r
-\r
-This method gets/sets the name of the input source (usually a filename).\r
-If no argument is given, it returns a string containing the name of\r
-the input source; otherwise it sets the name of the input source to the\r
-contents of the given argument.\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub name {\r
-   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];\r
-   return $_[0]->{'-name'};\r
-}\r
-\r
-## allow 'filename' as an alias for 'name'\r
-*filename = \&name;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head2 B<handle()>\r
-\r
-        my $handle = $pod_input->handle();\r
-\r
-Returns a reference to the handle object from which input is read (the\r
-one used to contructed this input source object).\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub handle {\r
-   return $_[0]->{'-handle'};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head2 B<was_cutting()>\r
-\r
-        print "Yes.\n" if ($pod_input->was_cutting());\r
-\r
-The value of the C<cutting> state (that the B<cutting()> method would\r
-have returned) immediately before any input was read from this input\r
-stream. After all input from this stream has been read, the C<cutting>\r
-state is restored to this value.\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub was_cutting {\r
-   (@_ > 1)  and  $_[0]->{-was_cutting} = $_[1];\r
-   return $_[0]->{-was_cutting};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-#############################################################################\r
-\r
-package Pod::Paragraph;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<Pod::Paragraph>\r
-\r
-An object representing a paragraph of POD input text.\r
-It has the following methods/attributes:\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 Pod::Paragraph-E<gt>B<new()>\r
-\r
-        my $pod_para1 = Pod::Paragraph->new(-text => $text);\r
-        my $pod_para2 = Pod::Paragraph->new(-name => $cmd,\r
-                                            -text => $text);\r
-        my $pod_para3 = new Pod::Paragraph(-text => $text);\r
-        my $pod_para4 = new Pod::Paragraph(-name => $cmd,\r
-                                           -text => $text);\r
-        my $pod_para5 = Pod::Paragraph->new(-name => $cmd,\r
-                                            -text => $text,\r
-                                            -file => $filename,\r
-                                            -line => $line_number);\r
-\r
-This is a class method that constructs a C<Pod::Paragraph> object and\r
-returns a reference to the new paragraph object. It may be given one or\r
-two keyword arguments. The C<-text> keyword indicates the corresponding\r
-text of the POD paragraph. The C<-name> keyword indicates the name of\r
-the corresponding POD command, such as C<head1> or C<item> (it should\r
-I<not> contain the C<=> prefix); this is needed only if the POD\r
-paragraph corresponds to a command paragraph. The C<-file> and C<-line>\r
-keywords indicate the filename and line number corresponding to the\r
-beginning of the paragraph \r
-\r
-=cut\r
-\r
-sub new {\r
-    ## Determine if we were called via an object-ref or a classname\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-\r
-    ## Any remaining arguments are treated as initial values for the\r
-    ## hash that is used to represent this object. Note that we default\r
-    ## certain values by specifying them *before* the arguments passed.\r
-    ## If they are in the argument list, they will override the defaults.\r
-    my $self = {\r
-          -name       => undef,\r
-          -text       => (@_ == 1) ? shift : undef,\r
-          -file       => '<unknown-file>',\r
-          -line       => 0,\r
-          -prefix     => '=',\r
-          -separator  => ' ',\r
-          -ptree => [],\r
-          @_\r
-    };\r
-\r
-    ## Bless ourselves into the desired class and perform any initialization\r
-    bless $self, $class;\r
-    return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<cmd_name()>\r
-\r
-        my $para_cmd = $pod_para->cmd_name();\r
-\r
-If this paragraph is a command paragraph, then this method will return \r
-the name of the command (I<without> any leading C<=> prefix).\r
-\r
-=cut\r
-\r
-sub cmd_name {\r
-   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];\r
-   return $_[0]->{'-name'};\r
-}\r
-\r
-## let name() be an alias for cmd_name()\r
-*name = \&cmd_name;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<text()>\r
-\r
-        my $para_text = $pod_para->text();\r
-\r
-This method will return the corresponding text of the paragraph.\r
-\r
-=cut\r
-\r
-sub text {\r
-   (@_ > 1)  and  $_[0]->{'-text'} = $_[1];\r
-   return $_[0]->{'-text'};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<raw_text()>\r
-\r
-        my $raw_pod_para = $pod_para->raw_text();\r
-\r
-This method will return the I<raw> text of the POD paragraph, exactly\r
-as it appeared in the input.\r
-\r
-=cut\r
-\r
-sub raw_text {\r
-   return $_[0]->{'-text'}  unless (defined $_[0]->{'-name'});\r
-   return $_[0]->{'-prefix'} . $_[0]->{'-name'} .\r
-          $_[0]->{'-separator'} . $_[0]->{'-text'};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<cmd_prefix()>\r
-\r
-        my $prefix = $pod_para->cmd_prefix();\r
-\r
-If this paragraph is a command paragraph, then this method will return \r
-the prefix used to denote the command (which should be the string "="\r
-or "==").\r
-\r
-=cut\r
-\r
-sub cmd_prefix {\r
-   return $_[0]->{'-prefix'};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<cmd_separator()>\r
-\r
-        my $separator = $pod_para->cmd_separator();\r
-\r
-If this paragraph is a command paragraph, then this method will return\r
-the text used to separate the command name from the rest of the\r
-paragraph (if any).\r
-\r
-=cut\r
-\r
-sub cmd_separator {\r
-   return $_[0]->{'-separator'};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<parse_tree()>\r
-\r
-        my $ptree = $pod_parser->parse_text( $pod_para->text() );\r
-        $pod_para->parse_tree( $ptree );\r
-        $ptree = $pod_para->parse_tree();\r
-\r
-This method will get/set the corresponding parse-tree of the paragraph's text.\r
-\r
-=cut\r
-\r
-sub parse_tree {\r
-   (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];\r
-   return $_[0]->{'-ptree'};\r
-}\r
-\r
-## let ptree() be an alias for parse_tree()\r
-*ptree = \&parse_tree;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_para-E<gt>B<file_line()>\r
-\r
-        my ($filename, $line_number) = $pod_para->file_line();\r
-        my $position = $pod_para->file_line();\r
-\r
-Returns the current filename and line number for the paragraph\r
-object.  If called in a list context, it returns a list of two\r
-elements: first the filename, then the line number. If called in\r
-a scalar context, it returns a string containing the filename, followed\r
-by a colon (':'), followed by the line number.\r
-\r
-=cut\r
-\r
-sub file_line {\r
-   my @loc = ($_[0]->{'-file'} || '<unknown-file>',\r
-              $_[0]->{'-line'} || 0);\r
-   return (wantarray) ? @loc : join(':', @loc);\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-#############################################################################\r
-\r
-package Pod::InteriorSequence;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<Pod::InteriorSequence>\r
-\r
-An object representing a POD interior sequence command.\r
-It has the following methods/attributes:\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 Pod::InteriorSequence-E<gt>B<new()>\r
-\r
-        my $pod_seq1 = Pod::InteriorSequence->new(-name => $cmd\r
-                                                  -ldelim => $delimiter);\r
-        my $pod_seq2 = new Pod::InteriorSequence(-name => $cmd,\r
-                                                 -ldelim => $delimiter);\r
-        my $pod_seq3 = new Pod::InteriorSequence(-name => $cmd,\r
-                                                 -ldelim => $delimiter,\r
-                                                 -file => $filename,\r
-                                                 -line => $line_number);\r
-\r
-        my $pod_seq4 = new Pod::InteriorSequence(-name => $cmd, $ptree);\r
-        my $pod_seq5 = new Pod::InteriorSequence($cmd, $ptree);\r
-\r
-This is a class method that constructs a C<Pod::InteriorSequence> object\r
-and returns a reference to the new interior sequence object. It should\r
-be given two keyword arguments.  The C<-ldelim> keyword indicates the\r
-corresponding left-delimiter of the interior sequence (e.g. 'E<lt>').\r
-The C<-name> keyword indicates the name of the corresponding interior\r
-sequence command, such as C<I> or C<B> or C<C>. The C<-file> and\r
-C<-line> keywords indicate the filename and line number corresponding\r
-to the beginning of the interior sequence. If the C<$ptree> argument is\r
-given, it must be the last argument, and it must be either string, or\r
-else an array-ref suitable for passing to B<Pod::ParseTree::new> (or\r
-it may be a reference to a Pod::ParseTree object).\r
-\r
-=cut\r
-\r
-sub new {\r
-    ## Determine if we were called via an object-ref or a classname\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-\r
-    ## See if first argument has no keyword\r
-    if (((@_ <= 2) or (@_ % 2)) and $_[0] !~ /^-\w/) {\r
-       ## Yup - need an implicit '-name' before first parameter\r
-       unshift @_, '-name';\r
-    }\r
-\r
-    ## See if odd number of args\r
-    if ((@_ % 2) != 0) {\r
-       ## Yup - need an implicit '-ptree' before the last parameter\r
-       splice @_, $#_, 0, '-ptree';\r
-    }\r
-\r
-    ## Any remaining arguments are treated as initial values for the\r
-    ## hash that is used to represent this object. Note that we default\r
-    ## certain values by specifying them *before* the arguments passed.\r
-    ## If they are in the argument list, they will override the defaults.\r
-    my $self = {\r
-          -name       => (@_ == 1) ? $_[0] : undef,\r
-          -file       => '<unknown-file>',\r
-          -line       => 0,\r
-          -ldelim     => '<',\r
-          -rdelim     => '>',\r
-          @_\r
-    };\r
-\r
-    ## Initialize contents if they haven't been already\r
-    my $ptree = $self->{'-ptree'} || new Pod::ParseTree();\r
-    if ( ref $ptree =~ /^(ARRAY)?$/ ) {\r
-        ## We have an array-ref, or a normal scalar. Pass it as an\r
-        ## an argument to the ptree-constructor\r
-        $ptree = new Pod::ParseTree($1 ? [$ptree] : $ptree);\r
-    }\r
-    $self->{'-ptree'} = $ptree;\r
-\r
-    ## Bless ourselves into the desired class and perform any initialization\r
-    bless $self, $class;\r
-    return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<cmd_name()>\r
-\r
-        my $seq_cmd = $pod_seq->cmd_name();\r
-\r
-The name of the interior sequence command.\r
-\r
-=cut\r
-\r
-sub cmd_name {\r
-   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];\r
-   return $_[0]->{'-name'};\r
-}\r
-\r
-## let name() be an alias for cmd_name()\r
-*name = \&cmd_name;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-## Private subroutine to set the parent pointer of all the given\r
-## children that are interior-sequences to be $self\r
-\r
-sub _set_child2parent_links {\r
-   my ($self, @children) = @_;\r
-   ## Make sure any sequences know who their parent is\r
-   for (@children) {\r
-      next  unless (length  and  ref  and  ref ne 'SCALAR');\r
-      if (UNIVERSAL::isa($_, 'Pod::InteriorSequence') or\r
-          UNIVERSAL::can($_, 'nested'))\r
-      {\r
-          $_->nested($self);\r
-      }\r
-   }\r
-}\r
-\r
-## Private subroutine to unset child->parent links\r
-\r
-sub _unset_child2parent_links {\r
-   my $self = shift;\r
-   $self->{'-parent_sequence'} = undef;\r
-   my $ptree = $self->{'-ptree'};\r
-   for (@$ptree) {\r
-      next  unless (length  and  ref  and  ref ne 'SCALAR');\r
-      $_->_unset_child2parent_links()\r
-          if UNIVERSAL::isa($_, 'Pod::InteriorSequence');\r
-   }\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<prepend()>\r
-\r
-        $pod_seq->prepend($text);\r
-        $pod_seq1->prepend($pod_seq2);\r
-\r
-Prepends the given string or parse-tree or sequence object to the parse-tree\r
-of this interior sequence.\r
-\r
-=cut\r
-\r
-sub prepend {\r
-   my $self  = shift;\r
-   $self->{'-ptree'}->prepend(@_);\r
-   _set_child2parent_links($self, @_);\r
-   return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<append()>\r
-\r
-        $pod_seq->append($text);\r
-        $pod_seq1->append($pod_seq2);\r
-\r
-Appends the given string or parse-tree or sequence object to the parse-tree\r
-of this interior sequence.\r
-\r
-=cut\r
-\r
-sub append {\r
-   my $self = shift;\r
-   $self->{'-ptree'}->append(@_);\r
-   _set_child2parent_links($self, @_);\r
-   return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<nested()>\r
-\r
-        $outer_seq = $pod_seq->nested || print "not nested";\r
-\r
-If this interior sequence is nested inside of another interior\r
-sequence, then the outer/parent sequence that contains it is\r
-returned. Otherwise C<undef> is returned.\r
-\r
-=cut\r
-\r
-sub nested {\r
-   my $self = shift;\r
-  (@_ == 1)  and  $self->{'-parent_sequence'} = shift;\r
-   return  $self->{'-parent_sequence'} || undef;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<raw_text()>\r
-\r
-        my $seq_raw_text = $pod_seq->raw_text();\r
-\r
-This method will return the I<raw> text of the POD interior sequence,\r
-exactly as it appeared in the input.\r
-\r
-=cut\r
-\r
-sub raw_text {\r
-   my $self = shift;\r
-   my $text = $self->{'-name'} . $self->{'-ldelim'};\r
-   for ( $self->{'-ptree'}->children ) {\r
-      $text .= (ref $_) ? $_->raw_text : $_;\r
-   }\r
-   $text .= $self->{'-rdelim'};\r
-   return $text;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<left_delimiter()>\r
-\r
-        my $ldelim = $pod_seq->left_delimiter();\r
-\r
-The leftmost delimiter beginning the argument text to the interior\r
-sequence (should be "<").\r
-\r
-=cut\r
-\r
-sub left_delimiter {\r
-   (@_ > 1)  and  $_[0]->{'-ldelim'} = $_[1];\r
-   return $_[0]->{'-ldelim'};\r
-}\r
-\r
-## let ldelim() be an alias for left_delimiter()\r
-*ldelim = \&left_delimiter;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<right_delimiter()>\r
-\r
-The rightmost delimiter beginning the argument text to the interior\r
-sequence (should be ">").\r
-\r
-=cut\r
-\r
-sub right_delimiter {\r
-   (@_ > 1)  and  $_[0]->{'-rdelim'} = $_[1];\r
-   return $_[0]->{'-rdelim'};\r
-}\r
-\r
-## let rdelim() be an alias for right_delimiter()\r
-*rdelim = \&right_delimiter;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<parse_tree()>\r
-\r
-        my $ptree = $pod_parser->parse_text($paragraph_text);\r
-        $pod_seq->parse_tree( $ptree );\r
-        $ptree = $pod_seq->parse_tree();\r
-\r
-This method will get/set the corresponding parse-tree of the interior\r
-sequence's text.\r
-\r
-=cut\r
-\r
-sub parse_tree {\r
-   (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];\r
-   return $_[0]->{'-ptree'};\r
-}\r
-\r
-## let ptree() be an alias for parse_tree()\r
-*ptree = \&parse_tree;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $pod_seq-E<gt>B<file_line()>\r
-\r
-        my ($filename, $line_number) = $pod_seq->file_line();\r
-        my $position = $pod_seq->file_line();\r
-\r
-Returns the current filename and line number for the interior sequence\r
-object.  If called in a list context, it returns a list of two\r
-elements: first the filename, then the line number. If called in\r
-a scalar context, it returns a string containing the filename, followed\r
-by a colon (':'), followed by the line number.\r
-\r
-=cut\r
-\r
-sub file_line {\r
-   my @loc = ($_[0]->{'-file'}  || '<unknown-file>',\r
-              $_[0]->{'-line'}  || 0);\r
-   return (wantarray) ? @loc : join(':', @loc);\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 Pod::InteriorSequence::B<DESTROY()>\r
-\r
-This method performs any necessary cleanup for the interior-sequence.\r
-If you override this method then it is B<imperative> that you invoke\r
-the parent method from within your own method, otherwise\r
-I<interior-sequence storage will not be reclaimed upon destruction!>\r
-\r
-=cut\r
-\r
-sub DESTROY {\r
-   ## We need to get rid of all child->parent pointers throughout the\r
-   ## tree so their reference counts will go to zero and they can be\r
-   ## garbage-collected\r
-   _unset_child2parent_links(@_);\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-#############################################################################\r
-\r
-package Pod::ParseTree;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<Pod::ParseTree>\r
-\r
-This object corresponds to a tree of parsed POD text. As POD text is\r
-scanned from left to right, it is parsed into an ordered list of\r
-text-strings and B<Pod::InteriorSequence> objects (in order of\r
-appearance). A B<Pod::ParseTree> object corresponds to this list of\r
-strings and sequences. Each interior sequence in the parse-tree may\r
-itself contain a parse-tree (since interior sequences may be nested).\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 Pod::ParseTree-E<gt>B<new()>\r
-\r
-        my $ptree1 = Pod::ParseTree->new;\r
-        my $ptree2 = new Pod::ParseTree;\r
-        my $ptree4 = Pod::ParseTree->new($array_ref);\r
-        my $ptree3 = new Pod::ParseTree($array_ref);\r
-\r
-This is a class method that constructs a C<Pod::Parse_tree> object and\r
-returns a reference to the new parse-tree. If a single-argument is given,\r
-it must be a reference to an array, and is used to initialize the root\r
-(top) of the parse tree.\r
-\r
-=cut\r
-\r
-sub new {\r
-    ## Determine if we were called via an object-ref or a classname\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-\r
-    my $self = (@_ == 1  and  ref $_[0]) ? $_[0] : [];\r
-\r
-    ## Bless ourselves into the desired class and perform any initialization\r
-    bless $self, $class;\r
-    return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $ptree-E<gt>B<top()>\r
-\r
-        my $top_node = $ptree->top();\r
-        $ptree->top( $top_node );\r
-        $ptree->top( @children );\r
-\r
-This method gets/sets the top node of the parse-tree. If no arguments are\r
-given, it returns the topmost node in the tree (the root), which is also\r
-a B<Pod::ParseTree>. If it is given a single argument that is a reference,\r
-then the reference is assumed to a parse-tree and becomes the new top node.\r
-Otherwise, if arguments are given, they are treated as the new list of\r
-children for the top node.\r
-\r
-=cut\r
-\r
-sub top {\r
-   my $self = shift;\r
-   if (@_ > 0) {\r
-      @{ $self } = (@_ == 1  and  ref $_[0]) ? ${ @_ } : @_;\r
-   }\r
-   return $self;\r
-}\r
-\r
-## let parse_tree() & ptree() be aliases for the 'top' method\r
-*parse_tree = *ptree = \&top;\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $ptree-E<gt>B<children()>\r
-\r
-This method gets/sets the children of the top node in the parse-tree.\r
-If no arguments are given, it returns the list (array) of children\r
-(each of which should be either a string or a B<Pod::InteriorSequence>.\r
-Otherwise, if arguments are given, they are treated as the new list of\r
-children for the top node.\r
-\r
-=cut\r
-\r
-sub children {\r
-   my $self = shift;\r
-   if (@_ > 0) {\r
-      @{ $self } = (@_ == 1  and  ref $_[0]) ? ${ @_ } : @_;\r
-   }\r
-   return @{ $self };\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $ptree-E<gt>B<prepend()>\r
-\r
-This method prepends the given text or parse-tree to the current parse-tree.\r
-If the first item on the parse-tree is text and the argument is also text,\r
-then the text is prepended to the first item (not added as a separate string).\r
-Otherwise the argument is added as a new string or parse-tree I<before>\r
-the current one.\r
-\r
-=cut\r
-\r
-use vars qw(@ptree);  ## an alias used for performance reasons\r
-\r
-sub prepend {\r
-   my $self = shift;\r
-   local *ptree = $self;\r
-   for (@_) {\r
-      next  unless length;\r
-      if (@ptree && !(ref $ptree[0]) && !(ref $_)) {\r
-         $ptree[0] = $_ . $ptree[0];\r
-      }\r
-      else {\r
-         unshift @ptree, $_;\r
-      }\r
-   }\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head2 $ptree-E<gt>B<append()>\r
-\r
-This method appends the given text or parse-tree to the current parse-tree.\r
-If the last item on the parse-tree is text and the argument is also text,\r
-then the text is appended to the last item (not added as a separate string).\r
-Otherwise the argument is added as a new string or parse-tree I<after>\r
-the current one.\r
-\r
-=cut\r
-\r
-sub append {\r
-   my $self = shift;\r
-   local *ptree = $self;\r
-   my $can_append = @ptree && !(ref $ptree[-1]);\r
-   for (@_) {\r
-      if (ref) {\r
-         push @ptree, $_;\r
-      }\r
-      elsif(!length) {\r
-         next;\r
-      }\r
-      elsif ($can_append) {\r
-         $ptree[-1] .= $_;\r
-      }\r
-      else {\r
-         push @ptree, $_;\r
-      }\r
-   }\r
-}\r
-\r
-=head2 $ptree-E<gt>B<raw_text()>\r
-\r
-        my $ptree_raw_text = $ptree->raw_text();\r
-\r
-This method will return the I<raw> text of the POD parse-tree\r
-exactly as it appeared in the input.\r
-\r
-=cut\r
-\r
-sub raw_text {\r
-   my $self = shift;\r
-   my $text = '';\r
-   for ( @$self ) {\r
-      $text .= (ref $_) ? $_->raw_text : $_;\r
-   }\r
-   return $text;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-## Private routines to set/unset child->parent links\r
-\r
-sub _unset_child2parent_links {\r
-   my $self = shift;\r
-   local *ptree = $self;\r
-   for (@ptree) {\r
-       next  unless (defined and length  and  ref  and  ref ne 'SCALAR');\r
-       $_->_unset_child2parent_links()\r
-           if UNIVERSAL::isa($_, 'Pod::InteriorSequence');\r
-   }\r
-}\r
-\r
-sub _set_child2parent_links {\r
-    ## nothing to do, Pod::ParseTrees cant have parent pointers\r
-}\r
-\r
-=head2 Pod::ParseTree::B<DESTROY()>\r
-\r
-This method performs any necessary cleanup for the parse-tree.\r
-If you override this method then it is B<imperative>\r
-that you invoke the parent method from within your own method,\r
-otherwise I<parse-tree storage will not be reclaimed upon destruction!>\r
-\r
-=cut\r
-\r
-sub DESTROY {\r
-   ## We need to get rid of all child->parent pointers throughout the\r
-   ## tree so their reference counts will go to zero and they can be\r
-   ## garbage-collected\r
-   _unset_child2parent_links(@_);\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 SEE ALSO\r
-\r
-B<Pod::InputObjects> is part of the L<Pod::Parser> distribution.\r
-\r
-See L<Pod::Parser>, L<Pod::Select>\r
-\r
-=head1 AUTHOR\r
-\r
-Please report bugs using L<http://rt.cpan.org>.\r
-\r
-Brad Appleton E<lt>bradapp@enteract.comE<gt>\r
-\r
-=cut\r
-\r
-1;\r
+#############################################################################
+# Pod/InputObjects.pm -- package which defines objects for input streams
+# and paragraphs and commands when parsing POD docs.
+#
+# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.
+# This file is part of "PodParser". PodParser is free software;
+# you can redistribute it and/or modify it under the same terms
+# as Perl itself.
+#############################################################################
+
+package Pod::InputObjects;
+use strict;
+
+use vars qw($VERSION);
+$VERSION = '1.62';  ## Current version of this package
+require  5.005;    ## requires this Perl version or later
+
+#############################################################################
+
+=head1 NAME
+
+Pod::InputObjects - objects representing POD input paragraphs, commands, etc.
+
+=head1 SYNOPSIS
+
+    use Pod::InputObjects;
+
+=head1 REQUIRES
+
+perl5.004, Carp
+
+=head1 EXPORTS
+
+Nothing.
+
+=head1 DESCRIPTION
+
+B<NOTE: This module is considered legacy; modern Perl releases (5.18 and
+higher) are going to remove Pod-Parser from core and use L<Pod-Simple>
+for all things POD.>
+
+This module defines some basic input objects used by B<Pod::Parser> when
+reading and parsing POD text from an input source. The following objects
+are defined:
+
+=begin __PRIVATE__
+
+=over 4
+
+=item package B<Pod::InputSource>
+
+An object corresponding to a source of POD input text. It is mostly a
+wrapper around a filehandle or C<IO::Handle>-type object (or anything
+that implements the C<getline()> method) which keeps track of some
+additional information relevant to the parsing of PODs.
+
+=back
+
+=end __PRIVATE__
+
+=over 4
+
+=item package B<Pod::Paragraph>
+
+An object corresponding to a paragraph of POD input text. It may be a
+plain paragraph, a verbatim paragraph, or a command paragraph (see
+L<perlpod>).
+
+=item package B<Pod::InteriorSequence>
+
+An object corresponding to an interior sequence command from the POD
+input text (see L<perlpod>).
+
+=item package B<Pod::ParseTree>
+
+An object corresponding to a tree of parsed POD text. Each "node" in
+a parse-tree (or I<ptree>) is either a text-string or a reference to
+a B<Pod::InteriorSequence> object. The nodes appear in the parse-tree
+in the order in which they were parsed from left-to-right.
+
+=back
+
+Each of these input objects are described in further detail in the
+sections which follow.
+
+=cut
+
+#############################################################################
+
+package Pod::InputSource;
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head1 B<Pod::InputSource>
+
+This object corresponds to an input source or stream of POD
+documentation. When parsing PODs, it is necessary to associate and store
+certain context information with each input source. All of this
+information is kept together with the stream itself in one of these
+C<Pod::InputSource> objects. Each such object is merely a wrapper around
+an C<IO::Handle> object of some kind (or at least something that
+implements the C<getline()> method). They have the following
+methods/attributes:
+
+=end __PRIVATE__
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head2 B<new()>
+
+        my $pod_input1 = Pod::InputSource->new(-handle => $filehandle);
+        my $pod_input2 = new Pod::InputSource(-handle => $filehandle,
+                                              -name   => $name);
+        my $pod_input3 = new Pod::InputSource(-handle => \*STDIN);
+        my $pod_input4 = Pod::InputSource->new(-handle => \*STDIN,
+                                               -name => "(STDIN)");
+
+This is a class method that constructs a C<Pod::InputSource> object and
+returns a reference to the new input source object. It takes one or more
+keyword arguments in the form of a hash. The keyword C<-handle> is
+required and designates the corresponding input handle. The keyword
+C<-name> is optional and specifies the name associated with the input
+handle (typically a file name).
+
+=end __PRIVATE__
+
+=cut
+
+sub new {
+    ## Determine if we were called via an object-ref or a classname
+    my $this = shift;
+    my $class = ref($this) || $this;
+
+    ## Any remaining arguments are treated as initial values for the
+    ## hash that is used to represent this object. Note that we default
+    ## certain values by specifying them *before* the arguments passed.
+    ## If they are in the argument list, they will override the defaults.
+    my $self = { -name        => '(unknown)',
+                 -handle      => undef,
+                 -was_cutting => 0,
+                 @_ };
+
+    ## Bless ourselves into the desired class and perform any initialization
+    bless $self, $class;
+    return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head2 B<name()>
+
+        my $filename = $pod_input->name();
+        $pod_input->name($new_filename_to_use);
+
+This method gets/sets the name of the input source (usually a filename).
+If no argument is given, it returns a string containing the name of
+the input source; otherwise it sets the name of the input source to the
+contents of the given argument.
+
+=end __PRIVATE__
+
+=cut
+
+sub name {
+   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];
+   return $_[0]->{'-name'};
+}
+
+## allow 'filename' as an alias for 'name'
+*filename = \&name;
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head2 B<handle()>
+
+        my $handle = $pod_input->handle();
+
+Returns a reference to the handle object from which input is read (the
+one used to contructed this input source object).
+
+=end __PRIVATE__
+
+=cut
+
+sub handle {
+   return $_[0]->{'-handle'};
+}
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head2 B<was_cutting()>
+
+        print "Yes.\n" if ($pod_input->was_cutting());
+
+The value of the C<cutting> state (that the B<cutting()> method would
+have returned) immediately before any input was read from this input
+stream. After all input from this stream has been read, the C<cutting>
+state is restored to this value.
+
+=end __PRIVATE__
+
+=cut
+
+sub was_cutting {
+   (@_ > 1)  and  $_[0]->{-was_cutting} = $_[1];
+   return $_[0]->{-was_cutting};
+}
+
+##---------------------------------------------------------------------------
+
+#############################################################################
+
+package Pod::Paragraph;
+
+##---------------------------------------------------------------------------
+
+=head1 B<Pod::Paragraph>
+
+An object representing a paragraph of POD input text.
+It has the following methods/attributes:
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head2 Pod::Paragraph-E<gt>B<new()>
+
+        my $pod_para1 = Pod::Paragraph->new(-text => $text);
+        my $pod_para2 = Pod::Paragraph->new(-name => $cmd,
+                                            -text => $text);
+        my $pod_para3 = new Pod::Paragraph(-text => $text);
+        my $pod_para4 = new Pod::Paragraph(-name => $cmd,
+                                           -text => $text);
+        my $pod_para5 = Pod::Paragraph->new(-name => $cmd,
+                                            -text => $text,
+                                            -file => $filename,
+                                            -line => $line_number);
+
+This is a class method that constructs a C<Pod::Paragraph> object and
+returns a reference to the new paragraph object. It may be given one or
+two keyword arguments. The C<-text> keyword indicates the corresponding
+text of the POD paragraph. The C<-name> keyword indicates the name of
+the corresponding POD command, such as C<head1> or C<item> (it should
+I<not> contain the C<=> prefix); this is needed only if the POD
+paragraph corresponds to a command paragraph. The C<-file> and C<-line>
+keywords indicate the filename and line number corresponding to the
+beginning of the paragraph 
+
+=cut
+
+sub new {
+    ## Determine if we were called via an object-ref or a classname
+    my $this = shift;
+    my $class = ref($this) || $this;
+
+    ## Any remaining arguments are treated as initial values for the
+    ## hash that is used to represent this object. Note that we default
+    ## certain values by specifying them *before* the arguments passed.
+    ## If they are in the argument list, they will override the defaults.
+    my $self = {
+          -name       => undef,
+          -text       => (@_ == 1) ? shift : undef,
+          -file       => '<unknown-file>',
+          -line       => 0,
+          -prefix     => '=',
+          -separator  => ' ',
+          -ptree => [],
+          @_
+    };
+
+    ## Bless ourselves into the desired class and perform any initialization
+    bless $self, $class;
+    return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<cmd_name()>
+
+        my $para_cmd = $pod_para->cmd_name();
+
+If this paragraph is a command paragraph, then this method will return 
+the name of the command (I<without> any leading C<=> prefix).
+
+=cut
+
+sub cmd_name {
+   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];
+   return $_[0]->{'-name'};
+}
+
+## let name() be an alias for cmd_name()
+*name = \&cmd_name;
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<text()>
+
+        my $para_text = $pod_para->text();
+
+This method will return the corresponding text of the paragraph.
+
+=cut
+
+sub text {
+   (@_ > 1)  and  $_[0]->{'-text'} = $_[1];
+   return $_[0]->{'-text'};
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<raw_text()>
+
+        my $raw_pod_para = $pod_para->raw_text();
+
+This method will return the I<raw> text of the POD paragraph, exactly
+as it appeared in the input.
+
+=cut
+
+sub raw_text {
+   return $_[0]->{'-text'}  unless (defined $_[0]->{'-name'});
+   return $_[0]->{'-prefix'} . $_[0]->{'-name'} .
+          $_[0]->{'-separator'} . $_[0]->{'-text'};
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<cmd_prefix()>
+
+        my $prefix = $pod_para->cmd_prefix();
+
+If this paragraph is a command paragraph, then this method will return 
+the prefix used to denote the command (which should be the string "="
+or "==").
+
+=cut
+
+sub cmd_prefix {
+   return $_[0]->{'-prefix'};
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<cmd_separator()>
+
+        my $separator = $pod_para->cmd_separator();
+
+If this paragraph is a command paragraph, then this method will return
+the text used to separate the command name from the rest of the
+paragraph (if any).
+
+=cut
+
+sub cmd_separator {
+   return $_[0]->{'-separator'};
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<parse_tree()>
+
+        my $ptree = $pod_parser->parse_text( $pod_para->text() );
+        $pod_para->parse_tree( $ptree );
+        $ptree = $pod_para->parse_tree();
+
+This method will get/set the corresponding parse-tree of the paragraph's text.
+
+=cut
+
+sub parse_tree {
+   (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];
+   return $_[0]->{'-ptree'};
+}
+
+## let ptree() be an alias for parse_tree()
+*ptree = \&parse_tree;
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_para-E<gt>B<file_line()>
+
+        my ($filename, $line_number) = $pod_para->file_line();
+        my $position = $pod_para->file_line();
+
+Returns the current filename and line number for the paragraph
+object.  If called in a list context, it returns a list of two
+elements: first the filename, then the line number. If called in
+a scalar context, it returns a string containing the filename, followed
+by a colon (':'), followed by the line number.
+
+=cut
+
+sub file_line {
+   my @loc = ($_[0]->{'-file'} || '<unknown-file>',
+              $_[0]->{'-line'} || 0);
+   return (wantarray) ? @loc : join(':', @loc);
+}
+
+##---------------------------------------------------------------------------
+
+#############################################################################
+
+package Pod::InteriorSequence;
+
+##---------------------------------------------------------------------------
+
+=head1 B<Pod::InteriorSequence>
+
+An object representing a POD interior sequence command.
+It has the following methods/attributes:
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head2 Pod::InteriorSequence-E<gt>B<new()>
+
+        my $pod_seq1 = Pod::InteriorSequence->new(-name => $cmd
+                                                  -ldelim => $delimiter);
+        my $pod_seq2 = new Pod::InteriorSequence(-name => $cmd,
+                                                 -ldelim => $delimiter);
+        my $pod_seq3 = new Pod::InteriorSequence(-name => $cmd,
+                                                 -ldelim => $delimiter,
+                                                 -file => $filename,
+                                                 -line => $line_number);
+
+        my $pod_seq4 = new Pod::InteriorSequence(-name => $cmd, $ptree);
+        my $pod_seq5 = new Pod::InteriorSequence($cmd, $ptree);
+
+This is a class method that constructs a C<Pod::InteriorSequence> object
+and returns a reference to the new interior sequence object. It should
+be given two keyword arguments.  The C<-ldelim> keyword indicates the
+corresponding left-delimiter of the interior sequence (e.g. 'E<lt>').
+The C<-name> keyword indicates the name of the corresponding interior
+sequence command, such as C<I> or C<B> or C<C>. The C<-file> and
+C<-line> keywords indicate the filename and line number corresponding
+to the beginning of the interior sequence. If the C<$ptree> argument is
+given, it must be the last argument, and it must be either string, or
+else an array-ref suitable for passing to B<Pod::ParseTree::new> (or
+it may be a reference to a Pod::ParseTree object).
+
+=cut
+
+sub new {
+    ## Determine if we were called via an object-ref or a classname
+    my $this = shift;
+    my $class = ref($this) || $this;
+
+    ## See if first argument has no keyword
+    if (((@_ <= 2) or (@_ % 2)) and $_[0] !~ /^-\w/) {
+       ## Yup - need an implicit '-name' before first parameter
+       unshift @_, '-name';
+    }
+
+    ## See if odd number of args
+    if ((@_ % 2) != 0) {
+       ## Yup - need an implicit '-ptree' before the last parameter
+       splice @_, $#_, 0, '-ptree';
+    }
+
+    ## Any remaining arguments are treated as initial values for the
+    ## hash that is used to represent this object. Note that we default
+    ## certain values by specifying them *before* the arguments passed.
+    ## If they are in the argument list, they will override the defaults.
+    my $self = {
+          -name       => (@_ == 1) ? $_[0] : undef,
+          -file       => '<unknown-file>',
+          -line       => 0,
+          -ldelim     => '<',
+          -rdelim     => '>',
+          @_
+    };
+
+    ## Initialize contents if they haven't been already
+    my $ptree = $self->{'-ptree'} || new Pod::ParseTree();
+    if ( ref $ptree =~ /^(ARRAY)?$/ ) {
+        ## We have an array-ref, or a normal scalar. Pass it as an
+        ## an argument to the ptree-constructor
+        $ptree = new Pod::ParseTree($1 ? [$ptree] : $ptree);
+    }
+    $self->{'-ptree'} = $ptree;
+
+    ## Bless ourselves into the desired class and perform any initialization
+    bless $self, $class;
+    return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<cmd_name()>
+
+        my $seq_cmd = $pod_seq->cmd_name();
+
+The name of the interior sequence command.
+
+=cut
+
+sub cmd_name {
+   (@_ > 1)  and  $_[0]->{'-name'} = $_[1];
+   return $_[0]->{'-name'};
+}
+
+## let name() be an alias for cmd_name()
+*name = \&cmd_name;
+
+##---------------------------------------------------------------------------
+
+## Private subroutine to set the parent pointer of all the given
+## children that are interior-sequences to be $self
+
+sub _set_child2parent_links {
+   my ($self, @children) = @_;
+   ## Make sure any sequences know who their parent is
+   for (@children) {
+      next  unless (length  and  ref  and  ref ne 'SCALAR');
+      if (UNIVERSAL::isa($_, 'Pod::InteriorSequence') or
+          UNIVERSAL::can($_, 'nested'))
+      {
+          $_->nested($self);
+      }
+   }
+}
+
+## Private subroutine to unset child->parent links
+
+sub _unset_child2parent_links {
+   my $self = shift;
+   $self->{'-parent_sequence'} = undef;
+   my $ptree = $self->{'-ptree'};
+   for (@$ptree) {
+      next  unless (length  and  ref  and  ref ne 'SCALAR');
+      $_->_unset_child2parent_links()
+          if UNIVERSAL::isa($_, 'Pod::InteriorSequence');
+   }
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<prepend()>
+
+        $pod_seq->prepend($text);
+        $pod_seq1->prepend($pod_seq2);
+
+Prepends the given string or parse-tree or sequence object to the parse-tree
+of this interior sequence.
+
+=cut
+
+sub prepend {
+   my $self  = shift;
+   $self->{'-ptree'}->prepend(@_);
+   _set_child2parent_links($self, @_);
+   return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<append()>
+
+        $pod_seq->append($text);
+        $pod_seq1->append($pod_seq2);
+
+Appends the given string or parse-tree or sequence object to the parse-tree
+of this interior sequence.
+
+=cut
+
+sub append {
+   my $self = shift;
+   $self->{'-ptree'}->append(@_);
+   _set_child2parent_links($self, @_);
+   return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<nested()>
+
+        $outer_seq = $pod_seq->nested || print "not nested";
+
+If this interior sequence is nested inside of another interior
+sequence, then the outer/parent sequence that contains it is
+returned. Otherwise C<undef> is returned.
+
+=cut
+
+sub nested {
+   my $self = shift;
+  (@_ == 1)  and  $self->{'-parent_sequence'} = shift;
+   return  $self->{'-parent_sequence'} || undef;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<raw_text()>
+
+        my $seq_raw_text = $pod_seq->raw_text();
+
+This method will return the I<raw> text of the POD interior sequence,
+exactly as it appeared in the input.
+
+=cut
+
+sub raw_text {
+   my $self = shift;
+   my $text = $self->{'-name'} . $self->{'-ldelim'};
+   for ( $self->{'-ptree'}->children ) {
+      $text .= (ref $_) ? $_->raw_text : $_;
+   }
+   $text .= $self->{'-rdelim'};
+   return $text;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<left_delimiter()>
+
+        my $ldelim = $pod_seq->left_delimiter();
+
+The leftmost delimiter beginning the argument text to the interior
+sequence (should be "<").
+
+=cut
+
+sub left_delimiter {
+   (@_ > 1)  and  $_[0]->{'-ldelim'} = $_[1];
+   return $_[0]->{'-ldelim'};
+}
+
+## let ldelim() be an alias for left_delimiter()
+*ldelim = \&left_delimiter;
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<right_delimiter()>
+
+The rightmost delimiter beginning the argument text to the interior
+sequence (should be ">").
+
+=cut
+
+sub right_delimiter {
+   (@_ > 1)  and  $_[0]->{'-rdelim'} = $_[1];
+   return $_[0]->{'-rdelim'};
+}
+
+## let rdelim() be an alias for right_delimiter()
+*rdelim = \&right_delimiter;
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<parse_tree()>
+
+        my $ptree = $pod_parser->parse_text($paragraph_text);
+        $pod_seq->parse_tree( $ptree );
+        $ptree = $pod_seq->parse_tree();
+
+This method will get/set the corresponding parse-tree of the interior
+sequence's text.
+
+=cut
+
+sub parse_tree {
+   (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];
+   return $_[0]->{'-ptree'};
+}
+
+## let ptree() be an alias for parse_tree()
+*ptree = \&parse_tree;
+
+##---------------------------------------------------------------------------
+
+=head2 $pod_seq-E<gt>B<file_line()>
+
+        my ($filename, $line_number) = $pod_seq->file_line();
+        my $position = $pod_seq->file_line();
+
+Returns the current filename and line number for the interior sequence
+object.  If called in a list context, it returns a list of two
+elements: first the filename, then the line number. If called in
+a scalar context, it returns a string containing the filename, followed
+by a colon (':'), followed by the line number.
+
+=cut
+
+sub file_line {
+   my @loc = ($_[0]->{'-file'}  || '<unknown-file>',
+              $_[0]->{'-line'}  || 0);
+   return (wantarray) ? @loc : join(':', @loc);
+}
+
+##---------------------------------------------------------------------------
+
+=head2 Pod::InteriorSequence::B<DESTROY()>
+
+This method performs any necessary cleanup for the interior-sequence.
+If you override this method then it is B<imperative> that you invoke
+the parent method from within your own method, otherwise
+I<interior-sequence storage will not be reclaimed upon destruction!>
+
+=cut
+
+sub DESTROY {
+   ## We need to get rid of all child->parent pointers throughout the
+   ## tree so their reference counts will go to zero and they can be
+   ## garbage-collected
+   _unset_child2parent_links(@_);
+}
+
+##---------------------------------------------------------------------------
+
+#############################################################################
+
+package Pod::ParseTree;
+
+##---------------------------------------------------------------------------
+
+=head1 B<Pod::ParseTree>
+
+This object corresponds to a tree of parsed POD text. As POD text is
+scanned from left to right, it is parsed into an ordered list of
+text-strings and B<Pod::InteriorSequence> objects (in order of
+appearance). A B<Pod::ParseTree> object corresponds to this list of
+strings and sequences. Each interior sequence in the parse-tree may
+itself contain a parse-tree (since interior sequences may be nested).
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head2 Pod::ParseTree-E<gt>B<new()>
+
+        my $ptree1 = Pod::ParseTree->new;
+        my $ptree2 = new Pod::ParseTree;
+        my $ptree4 = Pod::ParseTree->new($array_ref);
+        my $ptree3 = new Pod::ParseTree($array_ref);
+
+This is a class method that constructs a C<Pod::Parse_tree> object and
+returns a reference to the new parse-tree. If a single-argument is given,
+it must be a reference to an array, and is used to initialize the root
+(top) of the parse tree.
+
+=cut
+
+sub new {
+    ## Determine if we were called via an object-ref or a classname
+    my $this = shift;
+    my $class = ref($this) || $this;
+
+    my $self = (@_ == 1  and  ref $_[0]) ? $_[0] : [];
+
+    ## Bless ourselves into the desired class and perform any initialization
+    bless $self, $class;
+    return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $ptree-E<gt>B<top()>
+
+        my $top_node = $ptree->top();
+        $ptree->top( $top_node );
+        $ptree->top( @children );
+
+This method gets/sets the top node of the parse-tree. If no arguments are
+given, it returns the topmost node in the tree (the root), which is also
+a B<Pod::ParseTree>. If it is given a single argument that is a reference,
+then the reference is assumed to a parse-tree and becomes the new top node.
+Otherwise, if arguments are given, they are treated as the new list of
+children for the top node.
+
+=cut
+
+sub top {
+   my $self = shift;
+   if (@_ > 0) {
+      @{ $self } = (@_ == 1  and  ref $_[0]) ? ${ @_ } : @_;
+   }
+   return $self;
+}
+
+## let parse_tree() & ptree() be aliases for the 'top' method
+*parse_tree = *ptree = \&top;
+
+##---------------------------------------------------------------------------
+
+=head2 $ptree-E<gt>B<children()>
+
+This method gets/sets the children of the top node in the parse-tree.
+If no arguments are given, it returns the list (array) of children
+(each of which should be either a string or a B<Pod::InteriorSequence>.
+Otherwise, if arguments are given, they are treated as the new list of
+children for the top node.
+
+=cut
+
+sub children {
+   my $self = shift;
+   if (@_ > 0) {
+      @{ $self } = (@_ == 1  and  ref $_[0]) ? ${ @_ } : @_;
+   }
+   return @{ $self };
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $ptree-E<gt>B<prepend()>
+
+This method prepends the given text or parse-tree to the current parse-tree.
+If the first item on the parse-tree is text and the argument is also text,
+then the text is prepended to the first item (not added as a separate string).
+Otherwise the argument is added as a new string or parse-tree I<before>
+the current one.
+
+=cut
+
+use vars qw(@ptree);  ## an alias used for performance reasons
+
+sub prepend {
+   my $self = shift;
+   local *ptree = $self;
+   for (@_) {
+      next  unless length;
+      if (@ptree && !(ref $ptree[0]) && !(ref $_)) {
+         $ptree[0] = $_ . $ptree[0];
+      }
+      else {
+         unshift @ptree, $_;
+      }
+   }
+}
+
+##---------------------------------------------------------------------------
+
+=head2 $ptree-E<gt>B<append()>
+
+This method appends the given text or parse-tree to the current parse-tree.
+If the last item on the parse-tree is text and the argument is also text,
+then the text is appended to the last item (not added as a separate string).
+Otherwise the argument is added as a new string or parse-tree I<after>
+the current one.
+
+=cut
+
+sub append {
+   my $self = shift;
+   local *ptree = $self;
+   my $can_append = @ptree && !(ref $ptree[-1]);
+   for (@_) {
+      if (ref) {
+         push @ptree, $_;
+      }
+      elsif(!length) {
+         next;
+      }
+      elsif ($can_append) {
+         $ptree[-1] .= $_;
+      }
+      else {
+         push @ptree, $_;
+      }
+   }
+}
+
+=head2 $ptree-E<gt>B<raw_text()>
+
+        my $ptree_raw_text = $ptree->raw_text();
+
+This method will return the I<raw> text of the POD parse-tree
+exactly as it appeared in the input.
+
+=cut
+
+sub raw_text {
+   my $self = shift;
+   my $text = '';
+   for ( @$self ) {
+      $text .= (ref $_) ? $_->raw_text : $_;
+   }
+   return $text;
+}
+
+##---------------------------------------------------------------------------
+
+## Private routines to set/unset child->parent links
+
+sub _unset_child2parent_links {
+   my $self = shift;
+   local *ptree = $self;
+   for (@ptree) {
+       next  unless (defined and length  and  ref  and  ref ne 'SCALAR');
+       $_->_unset_child2parent_links()
+           if UNIVERSAL::isa($_, 'Pod::InteriorSequence');
+   }
+}
+
+sub _set_child2parent_links {
+    ## nothing to do, Pod::ParseTrees cant have parent pointers
+}
+
+=head2 Pod::ParseTree::B<DESTROY()>
+
+This method performs any necessary cleanup for the parse-tree.
+If you override this method then it is B<imperative>
+that you invoke the parent method from within your own method,
+otherwise I<parse-tree storage will not be reclaimed upon destruction!>
+
+=cut
+
+sub DESTROY {
+   ## We need to get rid of all child->parent pointers throughout the
+   ## tree so their reference counts will go to zero and they can be
+   ## garbage-collected
+   _unset_child2parent_links(@_);
+}
+
+#############################################################################
+
+=head1 SEE ALSO
+
+B<Pod::InputObjects> is part of the L<Pod::Parser> distribution.
+
+See L<Pod::Parser>, L<Pod::Select>
+
+=head1 AUTHOR
+
+Please report bugs using L<http://rt.cpan.org>.
+
+Brad Appleton E<lt>bradapp@enteract.comE<gt>
+
+=cut
+
+1;
index 551d594..e1ff2ae 100644 (file)
-#############################################################################\r
-# Pod/ParseUtils.pm -- helpers for POD parsing and conversion\r
-#\r
-# Copyright (C) 1999-2000 by Marek Rouchal. All rights reserved.\r
-# This file is part of "PodParser". PodParser is free software;\r
-# you can redistribute it and/or modify it under the same terms\r
-# as Perl itself.\r
-#############################################################################\r
-\r
-package Pod::ParseUtils;\r
-use strict;\r
-\r
-use vars qw($VERSION);\r
-$VERSION = '1.61'; ## Current version of this package\r
-require  5.005;    ## requires this Perl version or later\r
-\r
-=head1 NAME\r
-\r
-Pod::ParseUtils - helpers for POD parsing and conversion\r
-\r
-=head1 SYNOPSIS\r
-\r
-  use Pod::ParseUtils;\r
-\r
-  my $list = new Pod::List;\r
-  my $link = Pod::Hyperlink->new('Pod::Parser');\r
-\r
-=head1 DESCRIPTION\r
-\r
-B<Pod::ParseUtils> contains a few object-oriented helper packages for\r
-POD parsing and processing (i.e. in POD formatters and translators).\r
-\r
-=cut\r
-\r
-#-----------------------------------------------------------------------------\r
-# Pod::List\r
-#\r
-# class to hold POD list info (=over, =item, =back)\r
-#-----------------------------------------------------------------------------\r
-\r
-package Pod::List;\r
-\r
-use Carp;\r
-\r
-=head2 Pod::List\r
-\r
-B<Pod::List> can be used to hold information about POD lists\r
-(written as =over ... =item ... =back) for further processing.\r
-The following methods are available:\r
-\r
-=over 4\r
-\r
-=item Pod::List-E<gt>new()\r
-\r
-Create a new list object. Properties may be specified through a hash\r
-reference like this:\r
-\r
-  my $list = Pod::List->new({ -start => $., -indent => 4 });\r
-\r
-See the individual methods/properties for details.\r
-\r
-=cut\r
-\r
-sub new {\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-    my %params = @_;\r
-    my $self = {%params};\r
-    bless $self, $class;\r
-    $self->initialize();\r
-    return $self;\r
-}\r
-\r
-sub initialize {\r
-    my $self = shift;\r
-    $self->{-file} ||= 'unknown';\r
-    $self->{-start} ||= 'unknown';\r
-    $self->{-indent} ||= 4; # perlpod: "should be the default"\r
-    $self->{_items} = [];\r
-    $self->{-type} ||= '';\r
-}\r
-\r
-=item $list-E<gt>file()\r
-\r
-Without argument, retrieves the file name the list is in. This must\r
-have been set before by either specifying B<-file> in the B<new()>\r
-method or by calling the B<file()> method with a scalar argument.\r
-\r
-=cut\r
-\r
-# The POD file name the list appears in\r
-sub file {\r
-   return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};\r
-}\r
-\r
-=item $list-E<gt>start()\r
-\r
-Without argument, retrieves the line number where the list started.\r
-This must have been set before by either specifying B<-start> in the\r
-B<new()> method or by calling the B<start()> method with a scalar\r
-argument.\r
-\r
-=cut\r
-\r
-# The line in the file the node appears\r
-sub start {\r
-   return (@_ > 1) ? ($_[0]->{-start} = $_[1]) : $_[0]->{-start};\r
-}\r
-\r
-=item $list-E<gt>indent()\r
-\r
-Without argument, retrieves the indent level of the list as specified\r
-in C<=over n>. This must have been set before by either specifying\r
-B<-indent> in the B<new()> method or by calling the B<indent()> method\r
-with a scalar argument.\r
-\r
-=cut\r
-\r
-# indent level\r
-sub indent {\r
-   return (@_ > 1) ? ($_[0]->{-indent} = $_[1]) : $_[0]->{-indent};\r
-}\r
-\r
-=item $list-E<gt>type()\r
-\r
-Without argument, retrieves the list type, which can be an arbitrary value,\r
-e.g. C<OL>, C<UL>, ... when thinking the HTML way.\r
-This must have been set before by either specifying\r
-B<-type> in the B<new()> method or by calling the B<type()> method\r
-with a scalar argument.\r
-\r
-=cut\r
-\r
-# The type of the list (UL, OL, ...)\r
-sub type {\r
-   return (@_ > 1) ? ($_[0]->{-type} = $_[1]) : $_[0]->{-type};\r
-}\r
-\r
-=item $list-E<gt>rx()\r
-\r
-Without argument, retrieves a regular expression for simplifying the \r
-individual item strings once the list type has been determined. Usage:\r
-E.g. when converting to HTML, one might strip the leading number in\r
-an ordered list as C<E<lt>OLE<gt>> already prints numbers itself.\r
-This must have been set before by either specifying\r
-B<-rx> in the B<new()> method or by calling the B<rx()> method\r
-with a scalar argument.\r
-\r
-=cut\r
-\r
-# The regular expression to simplify the items\r
-sub rx {\r
-   return (@_ > 1) ? ($_[0]->{-rx} = $_[1]) : $_[0]->{-rx};\r
-}\r
-\r
-=item $list-E<gt>item()\r
-\r
-Without argument, retrieves the array of the items in this list.\r
-The items may be represented by any scalar.\r
-If an argument has been given, it is pushed on the list of items.\r
-\r
-=cut\r
-\r
-# The individual =items of this list\r
-sub item {\r
-    my ($self,$item) = @_;\r
-    if(defined $item) {\r
-        push(@{$self->{_items}}, $item);\r
-        return $item;\r
-    }\r
-    else {\r
-        return @{$self->{_items}};\r
-    }\r
-}\r
-\r
-=item $list-E<gt>parent()\r
-\r
-Without argument, retrieves information about the parent holding this\r
-list, which is represented as an arbitrary scalar.\r
-This must have been set before by either specifying\r
-B<-parent> in the B<new()> method or by calling the B<parent()> method\r
-with a scalar argument.\r
-\r
-=cut\r
-\r
-# possibility for parsers/translators to store information about the\r
-# lists's parent object\r
-sub parent {\r
-   return (@_ > 1) ? ($_[0]->{-parent} = $_[1]) : $_[0]->{-parent};\r
-}\r
-\r
-=item $list-E<gt>tag()\r
-\r
-Without argument, retrieves information about the list tag, which can be\r
-any scalar.\r
-This must have been set before by either specifying\r
-B<-tag> in the B<new()> method or by calling the B<tag()> method\r
-with a scalar argument.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-# possibility for parsers/translators to store information about the\r
-# list's object\r
-sub tag {\r
-   return (@_ > 1) ? ($_[0]->{-tag} = $_[1]) : $_[0]->{-tag};\r
-}\r
-\r
-#-----------------------------------------------------------------------------\r
-# Pod::Hyperlink\r
-#\r
-# class to manipulate POD hyperlinks (L<>)\r
-#-----------------------------------------------------------------------------\r
-\r
-package Pod::Hyperlink;\r
-\r
-=head2 Pod::Hyperlink\r
-\r
-B<Pod::Hyperlink> is a class for manipulation of POD hyperlinks. Usage:\r
-\r
-  my $link = Pod::Hyperlink->new('alternative text|page/"section in page"');\r
-\r
-The B<Pod::Hyperlink> class is mainly designed to parse the contents of the\r
-C<LE<lt>...E<gt>> sequence, providing a simple interface for accessing the\r
-different parts of a POD hyperlink for further processing. It can also be\r
-used to construct hyperlinks.\r
-\r
-=over 4\r
-\r
-=item Pod::Hyperlink-E<gt>new()\r
-\r
-The B<new()> method can either be passed a set of key/value pairs or a single\r
-scalar value, namely the contents of a C<LE<lt>...E<gt>> sequence. An object\r
-of the class C<Pod::Hyperlink> is returned. The value C<undef> indicates a\r
-failure, the error message is stored in C<$@>.\r
-\r
-=cut\r
-\r
-use Carp;\r
-\r
-sub new {\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-    my $self = +{};\r
-    bless $self, $class;\r
-    $self->initialize();\r
-    if(defined $_[0]) {\r
-        if(ref($_[0])) {\r
-            # called with a list of parameters\r
-            %$self = %{$_[0]};\r
-            $self->_construct_text();\r
-        }\r
-        else {\r
-            # called with L<> contents\r
-            return unless($self->parse($_[0]));\r
-        }\r
-    }\r
-    return $self;\r
-}\r
-\r
-sub initialize {\r
-    my $self = shift;\r
-    $self->{-line} ||= 'undef';\r
-    $self->{-file} ||= 'undef';\r
-    $self->{-page} ||= '';\r
-    $self->{-node} ||= '';\r
-    $self->{-alttext} ||= '';\r
-    $self->{-type} ||= 'undef';\r
-    $self->{_warnings} = [];\r
-}\r
-\r
-=item $link-E<gt>parse($string)\r
-\r
-This method can be used to (re)parse a (new) hyperlink, i.e. the contents\r
-of a C<LE<lt>...E<gt>> sequence. The result is stored in the current object.\r
-Warnings are stored in the B<warnings> property.\r
-E.g. sections like C<LE<lt>open(2)E<gt>> are deprecated, as they do not point\r
-to Perl documents. C<LE<lt>DBI::foo(3p)E<gt>> is wrong as well, the manpage\r
-section can simply be dropped.\r
-\r
-=cut\r
-\r
-sub parse {\r
-    my $self = shift;\r
-    local($_) = $_[0];\r
-    # syntax check the link and extract destination\r
-    my ($alttext,$page,$node,$type,$quoted) = (undef,'','','',0);\r
-\r
-    $self->{_warnings} = [];\r
-\r
-    # collapse newlines with whitespace\r
-    s/\s*\n+\s*/ /g;\r
-\r
-    # strip leading/trailing whitespace\r
-    if(s/^[\s\n]+//) {\r
-        $self->warning('ignoring leading whitespace in link');\r
-    }\r
-    if(s/[\s\n]+$//) {\r
-        $self->warning('ignoring trailing whitespace in link');\r
-    }\r
-    unless(length($_)) {\r
-        _invalid_link('empty link');\r
-        return;\r
-    }\r
-\r
-    ## Check for different possibilities. This is tedious and error-prone\r
-    # we match all possibilities (alttext, page, section/item)\r
-    #warn "DEBUG: link=$_\n";\r
-\r
-    # only page\r
-    # problem: a lot of people use (), or (1) or the like to indicate\r
-    # man page sections. But this collides with L<func()> that is supposed\r
-    # to point to an internal function...\r
-    my $page_rx = '[\w.-]+(?:::[\w.-]+)*(?:[(](?:\d\w*|)[)]|)';\r
-    # page name only\r
-    if(/^($page_rx)$/o) {\r
-        $page = $1;\r
-        $type = 'page';\r
-    }\r
-    # alttext, page and "section"\r
-    elsif(m{^(.*?)\s*[|]\s*($page_rx)\s*/\s*"(.+)"$}o) {\r
-        ($alttext, $page, $node) = ($1, $2, $3);\r
-        $type = 'section';\r
-        $quoted = 1; #... therefore | and / are allowed\r
-    }\r
-    # alttext and page\r
-    elsif(/^(.*?)\s*[|]\s*($page_rx)$/o) {\r
-        ($alttext, $page) = ($1, $2);\r
-        $type = 'page';\r
-    }\r
-    # alttext and "section"\r
-    elsif(m{^(.*?)\s*[|]\s*(?:/\s*|)"(.+)"$}) {\r
-        ($alttext, $node) = ($1,$2);\r
-        $type = 'section';\r
-        $quoted = 1;\r
-    }\r
-    # page and "section"\r
-    elsif(m{^($page_rx)\s*/\s*"(.+)"$}o) {\r
-        ($page, $node) = ($1, $2);\r
-        $type = 'section';\r
-        $quoted = 1;\r
-    }\r
-    # page and item\r
-    elsif(m{^($page_rx)\s*/\s*(.+)$}o) {\r
-        ($page, $node) = ($1, $2);\r
-        $type = 'item';\r
-    }\r
-    # only "section"\r
-    elsif(m{^/?"(.+)"$}) {\r
-        $node = $1;\r
-        $type = 'section';\r
-        $quoted = 1;\r
-    }\r
-    # only item\r
-    elsif(m{^\s*/(.+)$}) {\r
-        $node = $1;\r
-        $type = 'item';\r
-    }\r
-\r
-    # non-standard: Hyperlink with alt-text - doesn't remove protocol prefix, maybe it should?\r
-    elsif(/^ \s* (.*?) \s* [|] \s* (\w+:[^:\s] [^\s|]*?) \s* $/ix) {\r
-      ($alttext,$node) = ($1,$2);\r
-      $type = 'hyperlink';\r
-    }\r
-\r
-    # non-standard: Hyperlink\r
-    elsif(/^(\w+:[^:\s]\S*)$/i) {\r
-        $node = $1;\r
-        $type = 'hyperlink';\r
-    }\r
-    # alttext, page and item\r
-    elsif(m{^(.*?)\s*[|]\s*($page_rx)\s*/\s*(.+)$}o) {\r
-        ($alttext, $page, $node) = ($1, $2, $3);\r
-        $type = 'item';\r
-    }\r
-    # alttext and item\r
-    elsif(m{^(.*?)\s*[|]\s*/(.+)$}) {\r
-        ($alttext, $node) = ($1,$2);\r
-    }\r
-    # must be an item or a "malformed" section (without "")\r
-    else {\r
-        $node = $_;\r
-        $type = 'item';\r
-    }\r
-    # collapse whitespace in nodes\r
-    $node =~ s/\s+/ /gs;\r
-\r
-    # empty alternative text expands to node name\r
-    if(defined $alttext) {\r
-        if(!length($alttext)) {\r
-          $alttext = $node || $page;\r
-        }\r
-    }\r
-    else {\r
-        $alttext = '';\r
-    }\r
-\r
-    if($page =~ /[(]\w*[)]$/) {\r
-        $self->warning("(section) in '$page' deprecated");\r
-    }\r
-    if(!$quoted && $node =~ m{[|/]} && $type ne 'hyperlink') {\r
-        $self->warning("node '$node' contains non-escaped | or /");\r
-    }\r
-    if($alttext =~ m{[|/]}) {\r
-        $self->warning("alternative text '$node' contains non-escaped | or /");\r
-    }\r
-    $self->{-page} = $page;\r
-    $self->{-node} = $node;\r
-    $self->{-alttext} = $alttext;\r
-    #warn "DEBUG: page=$page section=$section item=$item alttext=$alttext\n";\r
-    $self->{-type} = $type;\r
-    $self->_construct_text();\r
-    1;\r
-}\r
-\r
-sub _construct_text {\r
-    my $self = shift;\r
-    my $alttext = $self->alttext();\r
-    my $type = $self->type();\r
-    my $section = $self->node();\r
-    my $page = $self->page();\r
-    my $page_ext = '';\r
-    $page =~ s/([(]\w*[)])$// && ($page_ext = $1);\r
-    if($alttext) {\r
-        $self->{_text} = $alttext;\r
-    }\r
-    elsif($type eq 'hyperlink') {\r
-        $self->{_text} = $section;\r
-    }\r
-    else {\r
-        $self->{_text} = ($section || '') .\r
-            (($page && $section) ? ' in ' : '') .\r
-            "$page$page_ext";\r
-    }\r
-    # for being marked up later\r
-    # use the non-standard markers P<> and Q<>, so that the resulting\r
-    # text can be parsed by the translators. It's their job to put\r
-    # the correct hypertext around the linktext\r
-    if($alttext) {\r
-        $self->{_markup} = "Q<$alttext>";\r
-    }\r
-    elsif($type eq 'hyperlink') {\r
-        $self->{_markup} = "Q<$section>";\r
-    }\r
-    else {\r
-        $self->{_markup} = (!$section ? '' : "Q<$section>") .\r
-            ($page ? ($section ? ' in ':'') . "P<$page>$page_ext" : '');\r
-    }\r
-}\r
-\r
-=item $link-E<gt>markup($string)\r
-\r
-Set/retrieve the textual value of the link. This string contains special\r
-markers C<PE<lt>E<gt>> and C<QE<lt>E<gt>> that should be expanded by the\r
-translator's interior sequence expansion engine to the\r
-formatter-specific code to highlight/activate the hyperlink. The details\r
-have to be implemented in the translator.\r
-\r
-=cut\r
-\r
-#' retrieve/set markuped text\r
-sub markup {\r
-    return (@_ > 1) ? ($_[0]->{_markup} = $_[1]) : $_[0]->{_markup};\r
-}\r
-\r
-=item $link-E<gt>text()\r
-\r
-This method returns the textual representation of the hyperlink as above,\r
-but without markers (read only). Depending on the link type this is one of\r
-the following alternatives (the + and * denote the portions of the text\r
-that are marked up):\r
-\r
-  +perl+                    L<perl>\r
-  *$|* in +perlvar+         L<perlvar/$|>\r
-  *OPTIONS* in +perldoc+    L<perldoc/"OPTIONS">\r
-  *DESCRIPTION*             L<"DESCRIPTION">\r
-\r
-=cut\r
-\r
-# The complete link's text\r
-sub text {\r
-    return $_[0]->{_text};\r
-}\r
-\r
-=item $link-E<gt>warning()\r
-\r
-After parsing, this method returns any warnings encountered during the\r
-parsing process.\r
-\r
-=cut\r
-\r
-# Set/retrieve warnings\r
-sub warning {\r
-    my $self = shift;\r
-    if(@_) {\r
-        push(@{$self->{_warnings}}, @_);\r
-        return @_;\r
-    }\r
-    return @{$self->{_warnings}};\r
-}\r
-\r
-=item $link-E<gt>file()\r
-\r
-=item $link-E<gt>line()\r
-\r
-Just simple slots for storing information about the line and the file\r
-the link was encountered in. Has to be filled in manually.\r
-\r
-=cut\r
-\r
-# The line in the file the link appears\r
-sub line {\r
-    return (@_ > 1) ? ($_[0]->{-line} = $_[1]) : $_[0]->{-line};\r
-}\r
-\r
-# The POD file name the link appears in\r
-sub file {\r
-    return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};\r
-}\r
-\r
-=item $link-E<gt>page()\r
-\r
-This method sets or returns the POD page this link points to.\r
-\r
-=cut\r
-\r
-# The POD page the link appears on\r
-sub page {\r
-    if (@_ > 1) {\r
-        $_[0]->{-page} = $_[1];\r
-        $_[0]->_construct_text();\r
-    }\r
-    return $_[0]->{-page};\r
-}\r
-\r
-=item $link-E<gt>node()\r
-\r
-As above, but the destination node text of the link.\r
-\r
-=cut\r
-\r
-# The link destination\r
-sub node {\r
-    if (@_ > 1) {\r
-        $_[0]->{-node} = $_[1];\r
-        $_[0]->_construct_text();\r
-    }\r
-    return $_[0]->{-node};\r
-}\r
-\r
-=item $link-E<gt>alttext()\r
-\r
-Sets or returns an alternative text specified in the link.\r
-\r
-=cut\r
-\r
-# Potential alternative text\r
-sub alttext {\r
-    if (@_ > 1) {\r
-        $_[0]->{-alttext} = $_[1];\r
-        $_[0]->_construct_text();\r
-    }\r
-    return $_[0]->{-alttext};\r
-}\r
-\r
-=item $link-E<gt>type()\r
-\r
-The node type, either C<section> or C<item>. As an unofficial type,\r
-there is also C<hyperlink>, derived from e.g. C<LE<lt>http://perl.comE<gt>>\r
-\r
-=cut\r
-\r
-# The type: item or headn\r
-sub type {\r
-    return (@_ > 1) ? ($_[0]->{-type} = $_[1]) : $_[0]->{-type};\r
-}\r
-\r
-=item $link-E<gt>link()\r
-\r
-Returns the link as contents of C<LE<lt>E<gt>>. Reciprocal to B<parse()>.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-# The link itself\r
-sub link {\r
-    my $self = shift;\r
-    my $link = $self->page() || '';\r
-    if($self->node()) {\r
-        my $node = $self->node();\r
-        $node =~ s/\|/E<verbar>/g;\r
-        $node =~ s{/}{E<sol>}g;\r
-        if($self->type() eq 'section') {\r
-            $link .= ($link ? '/' : '') . '"' . $node . '"';\r
-        }\r
-        elsif($self->type() eq 'hyperlink') {\r
-            $link = $self->node();\r
-        }\r
-        else { # item\r
-            $link .= '/' . $node;\r
-        }\r
-    }\r
-    if($self->alttext()) {\r
-        my $text = $self->alttext();\r
-        $text =~ s/\|/E<verbar>/g;\r
-        $text =~ s{/}{E<sol>}g;\r
-        $link = "$text|$link";\r
-    }\r
-    return $link;\r
-}\r
-\r
-sub _invalid_link {\r
-    my ($msg) = @_;\r
-    # this sets @_\r
-    #eval { die "$msg\n" };\r
-    #chomp $@;\r
-    $@ = $msg; # this seems to work, too!\r
-    return;\r
-}\r
-\r
-#-----------------------------------------------------------------------------\r
-# Pod::Cache\r
-#\r
-# class to hold POD page details\r
-#-----------------------------------------------------------------------------\r
-\r
-package Pod::Cache;\r
-\r
-=head2 Pod::Cache\r
-\r
-B<Pod::Cache> holds information about a set of POD documents,\r
-especially the nodes for hyperlinks.\r
-The following methods are available:\r
-\r
-=over 4\r
-\r
-=item Pod::Cache-E<gt>new()\r
-\r
-Create a new cache object. This object can hold an arbitrary number of\r
-POD documents of class Pod::Cache::Item.\r
-\r
-=cut\r
-\r
-sub new {\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-    my $self = [];\r
-    bless $self, $class;\r
-    return $self;\r
-}\r
-\r
-=item $cache-E<gt>item()\r
-\r
-Add a new item to the cache. Without arguments, this method returns a\r
-list of all cache elements.\r
-\r
-=cut\r
-\r
-sub item {\r
-    my ($self,%param) = @_;\r
-    if(%param) {\r
-        my $item = Pod::Cache::Item->new(%param);\r
-        push(@$self, $item);\r
-        return $item;\r
-    }\r
-    else {\r
-        return @{$self};\r
-    }\r
-}\r
-\r
-=item $cache-E<gt>find_page($name)\r
-\r
-Look for a POD document named C<$name> in the cache. Returns the\r
-reference to the corresponding Pod::Cache::Item object or undef if\r
-not found.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-sub find_page {\r
-    my ($self,$page) = @_;\r
-    foreach(@$self) {\r
-        if($_->page() eq $page) {\r
-            return $_;\r
-        }\r
-    }\r
-    return;\r
-}\r
-\r
-package Pod::Cache::Item;\r
-\r
-=head2 Pod::Cache::Item\r
-\r
-B<Pod::Cache::Item> holds information about individual POD documents,\r
-that can be grouped in a Pod::Cache object.\r
-It is intended to hold information about the hyperlink nodes of POD\r
-documents.\r
-The following methods are available:\r
-\r
-=over 4\r
-\r
-=item Pod::Cache::Item-E<gt>new()\r
-\r
-Create a new object.\r
-\r
-=cut\r
-\r
-sub new {\r
-    my $this = shift;\r
-    my $class = ref($this) || $this;\r
-    my %params = @_;\r
-    my $self = {%params};\r
-    bless $self, $class;\r
-    $self->initialize();\r
-    return $self;\r
-}\r
-\r
-sub initialize {\r
-    my $self = shift;\r
-    $self->{-nodes} = [] unless(defined $self->{-nodes});\r
-}\r
-\r
-=item $cacheitem-E<gt>page()\r
-\r
-Set/retrieve the POD document name (e.g. "Pod::Parser").\r
-\r
-=cut\r
-\r
-# The POD page\r
-sub page {\r
-   return (@_ > 1) ? ($_[0]->{-page} = $_[1]) : $_[0]->{-page};\r
-}\r
-\r
-=item $cacheitem-E<gt>description()\r
-\r
-Set/retrieve the POD short description as found in the C<=head1 NAME>\r
-section.\r
-\r
-=cut\r
-\r
-# The POD description, taken out of NAME if present\r
-sub description {\r
-   return (@_ > 1) ? ($_[0]->{-description} = $_[1]) : $_[0]->{-description};\r
-}\r
-\r
-=item $cacheitem-E<gt>path()\r
-\r
-Set/retrieve the POD file storage path.\r
-\r
-=cut\r
-\r
-# The file path\r
-sub path {\r
-   return (@_ > 1) ? ($_[0]->{-path} = $_[1]) : $_[0]->{-path};\r
-}\r
-\r
-=item $cacheitem-E<gt>file()\r
-\r
-Set/retrieve the POD file name.\r
-\r
-=cut\r
-\r
-# The POD file name\r
-sub file {\r
-   return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};\r
-}\r
-\r
-=item $cacheitem-E<gt>nodes()\r
-\r
-Add a node (or a list of nodes) to the document's node list. Note that\r
-the order is kept, i.e. start with the first node and end with the last.\r
-If no argument is given, the current list of nodes is returned in the\r
-same order the nodes have been added.\r
-A node can be any scalar, but usually is a pair of node string and\r
-unique id for the C<find_node> method to work correctly.\r
-\r
-=cut\r
-\r
-# The POD nodes\r
-sub nodes {\r
-    my ($self,@nodes) = @_;\r
-    if(@nodes) {\r
-        push(@{$self->{-nodes}}, @nodes);\r
-        return @nodes;\r
-    }\r
-    else {\r
-        return @{$self->{-nodes}};\r
-    }\r
-}\r
-\r
-=item $cacheitem-E<gt>find_node($name)\r
-\r
-Look for a node or index entry named C<$name> in the object.\r
-Returns the unique id of the node (i.e. the second element of the array\r
-stored in the node array) or undef if not found.\r
-\r
-=cut\r
-\r
-sub find_node {\r
-    my ($self,$node) = @_;\r
-    my @search;\r
-    push(@search, @{$self->{-nodes}}) if($self->{-nodes});\r
-    push(@search, @{$self->{-idx}}) if($self->{-idx});\r
-    foreach(@search) {\r
-        if($_->[0] eq $node) {\r
-            return $_->[1]; # id\r
-        }\r
-    }\r
-    return;\r
-}\r
-\r
-=item $cacheitem-E<gt>idx()\r
-\r
-Add an index entry (or a list of them) to the document's index list. Note that\r
-the order is kept, i.e. start with the first node and end with the last.\r
-If no argument is given, the current list of index entries is returned in the\r
-same order the entries have been added.\r
-An index entry can be any scalar, but usually is a pair of string and\r
-unique id.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-# The POD index entries\r
-sub idx {\r
-    my ($self,@idx) = @_;\r
-    if(@idx) {\r
-        push(@{$self->{-idx}}, @idx);\r
-        return @idx;\r
-    }\r
-    else {\r
-        return @{$self->{-idx}};\r
-    }\r
-}\r
-\r
-=head1 AUTHOR\r
-\r
-Please report bugs using L<http://rt.cpan.org>.\r
-\r
-Marek Rouchal E<lt>marekr@cpan.orgE<gt>, borrowing\r
-a lot of things from L<pod2man> and L<pod2roff> as well as other POD\r
-processing tools by Tom Christiansen, Brad Appleton and Russ Allbery.\r
-\r
-B<Pod::ParseUtils> is part of the L<Pod::Parser> distribution.\r
-\r
-=head1 SEE ALSO\r
-\r
-L<pod2man>, L<pod2roff>, L<Pod::Parser>, L<Pod::Checker>,\r
-L<pod2html>\r
-\r
-=cut\r
-\r
-1;\r
+#############################################################################
+# Pod/ParseUtils.pm -- helpers for POD parsing and conversion
+#
+# Copyright (C) 1999-2000 by Marek Rouchal. All rights reserved.
+# This file is part of "PodParser". PodParser is free software;
+# you can redistribute it and/or modify it under the same terms
+# as Perl itself.
+#############################################################################
+
+package Pod::ParseUtils;
+use strict;
+
+use vars qw($VERSION);
+$VERSION = '1.62'; ## Current version of this package
+require  5.005;    ## requires this Perl version or later
+
+=head1 NAME
+
+Pod::ParseUtils - helpers for POD parsing and conversion
+
+=head1 SYNOPSIS
+
+  use Pod::ParseUtils;
+
+  my $list = new Pod::List;
+  my $link = Pod::Hyperlink->new('Pod::Parser');
+
+=head1 DESCRIPTION
+
+B<NOTE: This module is considered legacy; modern Perl releases (5.18 and
+higher) are going to remove Pod-Parser from core and use L<Pod-Simple>
+for all things POD.>
+
+B<Pod::ParseUtils> contains a few object-oriented helper packages for
+POD parsing and processing (i.e. in POD formatters and translators).
+
+=cut
+
+#-----------------------------------------------------------------------------
+# Pod::List
+#
+# class to hold POD list info (=over, =item, =back)
+#-----------------------------------------------------------------------------
+
+package Pod::List;
+
+use Carp;
+
+=head2 Pod::List
+
+B<Pod::List> can be used to hold information about POD lists
+(written as =over ... =item ... =back) for further processing.
+The following methods are available:
+
+=over 4
+
+=item Pod::List-E<gt>new()
+
+Create a new list object. Properties may be specified through a hash
+reference like this:
+
+  my $list = Pod::List->new({ -start => $., -indent => 4 });
+
+See the individual methods/properties for details.
+
+=cut
+
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my %params = @_;
+    my $self = {%params};
+    bless $self, $class;
+    $self->initialize();
+    return $self;
+}
+
+sub initialize {
+    my $self = shift;
+    $self->{-file} ||= 'unknown';
+    $self->{-start} ||= 'unknown';
+    $self->{-indent} ||= 4; # perlpod: "should be the default"
+    $self->{_items} = [];
+    $self->{-type} ||= '';
+}
+
+=item $list-E<gt>file()
+
+Without argument, retrieves the file name the list is in. This must
+have been set before by either specifying B<-file> in the B<new()>
+method or by calling the B<file()> method with a scalar argument.
+
+=cut
+
+# The POD file name the list appears in
+sub file {
+   return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};
+}
+
+=item $list-E<gt>start()
+
+Without argument, retrieves the line number where the list started.
+This must have been set before by either specifying B<-start> in the
+B<new()> method or by calling the B<start()> method with a scalar
+argument.
+
+=cut
+
+# The line in the file the node appears
+sub start {
+   return (@_ > 1) ? ($_[0]->{-start} = $_[1]) : $_[0]->{-start};
+}
+
+=item $list-E<gt>indent()
+
+Without argument, retrieves the indent level of the list as specified
+in C<=over n>. This must have been set before by either specifying
+B<-indent> in the B<new()> method or by calling the B<indent()> method
+with a scalar argument.
+
+=cut
+
+# indent level
+sub indent {
+   return (@_ > 1) ? ($_[0]->{-indent} = $_[1]) : $_[0]->{-indent};
+}
+
+=item $list-E<gt>type()
+
+Without argument, retrieves the list type, which can be an arbitrary value,
+e.g. C<OL>, C<UL>, ... when thinking the HTML way.
+This must have been set before by either specifying
+B<-type> in the B<new()> method or by calling the B<type()> method
+with a scalar argument.
+
+=cut
+
+# The type of the list (UL, OL, ...)
+sub type {
+   return (@_ > 1) ? ($_[0]->{-type} = $_[1]) : $_[0]->{-type};
+}
+
+=item $list-E<gt>rx()
+
+Without argument, retrieves a regular expression for simplifying the 
+individual item strings once the list type has been determined. Usage:
+E.g. when converting to HTML, one might strip the leading number in
+an ordered list as C<E<lt>OLE<gt>> already prints numbers itself.
+This must have been set before by either specifying
+B<-rx> in the B<new()> method or by calling the B<rx()> method
+with a scalar argument.
+
+=cut
+
+# The regular expression to simplify the items
+sub rx {
+   return (@_ > 1) ? ($_[0]->{-rx} = $_[1]) : $_[0]->{-rx};
+}
+
+=item $list-E<gt>item()
+
+Without argument, retrieves the array of the items in this list.
+The items may be represented by any scalar.
+If an argument has been given, it is pushed on the list of items.
+
+=cut
+
+# The individual =items of this list
+sub item {
+    my ($self,$item) = @_;
+    if(defined $item) {
+        push(@{$self->{_items}}, $item);
+        return $item;
+    }
+    else {
+        return @{$self->{_items}};
+    }
+}
+
+=item $list-E<gt>parent()
+
+Without argument, retrieves information about the parent holding this
+list, which is represented as an arbitrary scalar.
+This must have been set before by either specifying
+B<-parent> in the B<new()> method or by calling the B<parent()> method
+with a scalar argument.
+
+=cut
+
+# possibility for parsers/translators to store information about the
+# lists's parent object
+sub parent {
+   return (@_ > 1) ? ($_[0]->{-parent} = $_[1]) : $_[0]->{-parent};
+}
+
+=item $list-E<gt>tag()
+
+Without argument, retrieves information about the list tag, which can be
+any scalar.
+This must have been set before by either specifying
+B<-tag> in the B<new()> method or by calling the B<tag()> method
+with a scalar argument.
+
+=back
+
+=cut
+
+# possibility for parsers/translators to store information about the
+# list's object
+sub tag {
+   return (@_ > 1) ? ($_[0]->{-tag} = $_[1]) : $_[0]->{-tag};
+}
+
+#-----------------------------------------------------------------------------
+# Pod::Hyperlink
+#
+# class to manipulate POD hyperlinks (L<>)
+#-----------------------------------------------------------------------------
+
+package Pod::Hyperlink;
+
+=head2 Pod::Hyperlink
+
+B<Pod::Hyperlink> is a class for manipulation of POD hyperlinks. Usage:
+
+  my $link = Pod::Hyperlink->new('alternative text|page/"section in page"');
+
+The B<Pod::Hyperlink> class is mainly designed to parse the contents of the
+C<LE<lt>...E<gt>> sequence, providing a simple interface for accessing the
+different parts of a POD hyperlink for further processing. It can also be
+used to construct hyperlinks.
+
+=over 4
+
+=item Pod::Hyperlink-E<gt>new()
+
+The B<new()> method can either be passed a set of key/value pairs or a single
+scalar value, namely the contents of a C<LE<lt>...E<gt>> sequence. An object
+of the class C<Pod::Hyperlink> is returned. The value C<undef> indicates a
+failure, the error message is stored in C<$@>.
+
+=cut
+
+use Carp;
+
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my $self = +{};
+    bless $self, $class;
+    $self->initialize();
+    if(defined $_[0]) {
+        if(ref($_[0])) {
+            # called with a list of parameters
+            %$self = %{$_[0]};
+            $self->_construct_text();
+        }
+        else {
+            # called with L<> contents
+            return unless($self->parse($_[0]));
+        }
+    }
+    return $self;
+}
+
+sub initialize {
+    my $self = shift;
+    $self->{-line} ||= 'undef';
+    $self->{-file} ||= 'undef';
+    $self->{-page} ||= '';
+    $self->{-node} ||= '';
+    $self->{-alttext} ||= '';
+    $self->{-type} ||= 'undef';
+    $self->{_warnings} = [];
+}
+
+=item $link-E<gt>parse($string)
+
+This method can be used to (re)parse a (new) hyperlink, i.e. the contents
+of a C<LE<lt>...E<gt>> sequence. The result is stored in the current object.
+Warnings are stored in the B<warnings> property.
+E.g. sections like C<LE<lt>open(2)E<gt>> are deprecated, as they do not point
+to Perl documents. C<LE<lt>DBI::foo(3p)E<gt>> is wrong as well, the manpage
+section can simply be dropped.
+
+=cut
+
+sub parse {
+    my $self = shift;
+    local($_) = $_[0];
+    # syntax check the link and extract destination
+    my ($alttext,$page,$node,$type,$quoted) = (undef,'','','',0);
+
+    $self->{_warnings} = [];
+
+    # collapse newlines with whitespace
+    s/\s*\n+\s*/ /g;
+
+    # strip leading/trailing whitespace
+    if(s/^[\s\n]+//) {
+        $self->warning('ignoring leading whitespace in link');
+    }
+    if(s/[\s\n]+$//) {
+        $self->warning('ignoring trailing whitespace in link');
+    }
+    unless(length($_)) {
+        _invalid_link('empty link');
+        return;
+    }
+
+    ## Check for different possibilities. This is tedious and error-prone
+    # we match all possibilities (alttext, page, section/item)
+    #warn "DEBUG: link=$_\n";
+
+    # only page
+    # problem: a lot of people use (), or (1) or the like to indicate
+    # man page sections. But this collides with L<func()> that is supposed
+    # to point to an internal function...
+    my $page_rx = '[\w.-]+(?:::[\w.-]+)*(?:[(](?:\d\w*|)[)]|)';
+    # page name only
+    if(/^($page_rx)$/o) {
+        $page = $1;
+        $type = 'page';
+    }
+    # alttext, page and "section"
+    elsif(m{^(.*?)\s*[|]\s*($page_rx)\s*/\s*"(.+)"$}o) {
+        ($alttext, $page, $node) = ($1, $2, $3);
+        $type = 'section';
+        $quoted = 1; #... therefore | and / are allowed
+    }
+    # alttext and page
+    elsif(/^(.*?)\s*[|]\s*($page_rx)$/o) {
+        ($alttext, $page) = ($1, $2);
+        $type = 'page';
+    }
+    # alttext and "section"
+    elsif(m{^(.*?)\s*[|]\s*(?:/\s*|)"(.+)"$}) {
+        ($alttext, $node) = ($1,$2);
+        $type = 'section';
+        $quoted = 1;
+    }
+    # page and "section"
+    elsif(m{^($page_rx)\s*/\s*"(.+)"$}o) {
+        ($page, $node) = ($1, $2);
+        $type = 'section';
+        $quoted = 1;
+    }
+    # page and item
+    elsif(m{^($page_rx)\s*/\s*(.+)$}o) {
+        ($page, $node) = ($1, $2);
+        $type = 'item';
+    }
+    # only "section"
+    elsif(m{^/?"(.+)"$}) {
+        $node = $1;
+        $type = 'section';
+        $quoted = 1;
+    }
+    # only item
+    elsif(m{^\s*/(.+)$}) {
+        $node = $1;
+        $type = 'item';
+    }
+
+    # non-standard: Hyperlink with alt-text - doesn't remove protocol prefix, maybe it should?
+    elsif(/^ \s* (.*?) \s* [|] \s* (\w+:[^:\s] [^\s|]*?) \s* $/ix) {
+      ($alttext,$node) = ($1,$2);
+      $type = 'hyperlink';
+    }
+
+    # non-standard: Hyperlink
+    elsif(/^(\w+:[^:\s]\S*)$/i) {
+        $node = $1;
+        $type = 'hyperlink';
+    }
+    # alttext, page and item
+    elsif(m{^(.*?)\s*[|]\s*($page_rx)\s*/\s*(.+)$}o) {
+        ($alttext, $page, $node) = ($1, $2, $3);
+        $type = 'item';
+    }
+    # alttext and item
+    elsif(m{^(.*?)\s*[|]\s*/(.+)$}) {
+        ($alttext, $node) = ($1,$2);
+    }
+    # must be an item or a "malformed" section (without "")
+    else {
+        $node = $_;
+        $type = 'item';
+    }
+    # collapse whitespace in nodes
+    $node =~ s/\s+/ /gs;
+
+    # empty alternative text expands to node name
+    if(defined $alttext) {
+        if(!length($alttext)) {
+          $alttext = $node || $page;
+        }
+    }
+    else {
+        $alttext = '';
+    }
+
+    if($page =~ /[(]\w*[)]$/) {
+        $self->warning("(section) in '$page' deprecated");
+    }
+    if(!$quoted && $node =~ m{[|/]} && $type ne 'hyperlink') {
+        $self->warning("node '$node' contains non-escaped | or /");
+    }
+    if($alttext =~ m{[|/]}) {
+        $self->warning("alternative text '$node' contains non-escaped | or /");
+    }
+    $self->{-page} = $page;
+    $self->{-node} = $node;
+    $self->{-alttext} = $alttext;
+    #warn "DEBUG: page=$page section=$section item=$item alttext=$alttext\n";
+    $self->{-type} = $type;
+    $self->_construct_text();
+    1;
+}
+
+sub _construct_text {
+    my $self = shift;
+    my $alttext = $self->alttext();
+    my $type = $self->type();
+    my $section = $self->node();
+    my $page = $self->page();
+    my $page_ext = '';
+    $page =~ s/([(]\w*[)])$// && ($page_ext = $1);
+    if($alttext) {
+        $self->{_text} = $alttext;
+    }
+    elsif($type eq 'hyperlink') {
+        $self->{_text} = $section;
+    }
+    else {
+        $self->{_text} = ($section || '') .
+            (($page && $section) ? ' in ' : '') .
+            "$page$page_ext";
+    }
+    # for being marked up later
+    # use the non-standard markers P<> and Q<>, so that the resulting
+    # text can be parsed by the translators. It's their job to put
+    # the correct hypertext around the linktext
+    if($alttext) {
+        $self->{_markup} = "Q<$alttext>";
+    }
+    elsif($type eq 'hyperlink') {
+        $self->{_markup} = "Q<$section>";
+    }
+    else {
+        $self->{_markup} = (!$section ? '' : "Q<$section>") .
+            ($page ? ($section ? ' in ':'') . "P<$page>$page_ext" : '');
+    }
+}
+
+=item $link-E<gt>markup($string)
+
+Set/retrieve the textual value of the link. This string contains special
+markers C<PE<lt>E<gt>> and C<QE<lt>E<gt>> that should be expanded by the
+translator's interior sequence expansion engine to the
+formatter-specific code to highlight/activate the hyperlink. The details
+have to be implemented in the translator.
+
+=cut
+
+#' retrieve/set markuped text
+sub markup {
+    return (@_ > 1) ? ($_[0]->{_markup} = $_[1]) : $_[0]->{_markup};
+}
+
+=item $link-E<gt>text()
+
+This method returns the textual representation of the hyperlink as above,
+but without markers (read only). Depending on the link type this is one of
+the following alternatives (the + and * denote the portions of the text
+that are marked up):
+
+  +perl+                    L<perl>
+  *$|* in +perlvar+         L<perlvar/$|>
+  *OPTIONS* in +perldoc+    L<perldoc/"OPTIONS">
+  *DESCRIPTION*             L<"DESCRIPTION">
+
+=cut
+
+# The complete link's text
+sub text {
+    return $_[0]->{_text};
+}
+
+=item $link-E<gt>warning()
+
+After parsing, this method returns any warnings encountered during the
+parsing process.
+
+=cut
+
+# Set/retrieve warnings
+sub warning {
+    my $self = shift;
+    if(@_) {
+        push(@{$self->{_warnings}}, @_);
+        return @_;
+    }
+    return @{$self->{_warnings}};
+}
+
+=item $link-E<gt>file()
+
+=item $link-E<gt>line()
+
+Just simple slots for storing information about the line and the file
+the link was encountered in. Has to be filled in manually.
+
+=cut
+
+# The line in the file the link appears
+sub line {
+    return (@_ > 1) ? ($_[0]->{-line} = $_[1]) : $_[0]->{-line};
+}
+
+# The POD file name the link appears in
+sub file {
+    return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};
+}
+
+=item $link-E<gt>page()
+
+This method sets or returns the POD page this link points to.
+
+=cut
+
+# The POD page the link appears on
+sub page {
+    if (@_ > 1) {
+        $_[0]->{-page} = $_[1];
+        $_[0]->_construct_text();
+    }
+    return $_[0]->{-page};
+}
+
+=item $link-E<gt>node()
+
+As above, but the destination node text of the link.
+
+=cut
+
+# The link destination
+sub node {
+    if (@_ > 1) {
+        $_[0]->{-node} = $_[1];
+        $_[0]->_construct_text();
+    }
+    return $_[0]->{-node};
+}
+
+=item $link-E<gt>alttext()
+
+Sets or returns an alternative text specified in the link.
+
+=cut
+
+# Potential alternative text
+sub alttext {
+    if (@_ > 1) {
+        $_[0]->{-alttext} = $_[1];
+        $_[0]->_construct_text();
+    }
+    return $_[0]->{-alttext};
+}
+
+=item $link-E<gt>type()
+
+The node type, either C<section> or C<item>. As an unofficial type,
+there is also C<hyperlink>, derived from e.g. C<LE<lt>http://perl.comE<gt>>
+
+=cut
+
+# The type: item or headn
+sub type {
+    return (@_ > 1) ? ($_[0]->{-type} = $_[1]) : $_[0]->{-type};
+}
+
+=item $link-E<gt>link()
+
+Returns the link as contents of C<LE<lt>E<gt>>. Reciprocal to B<parse()>.
+
+=back
+
+=cut
+
+# The link itself
+sub link {
+    my $self = shift;
+    my $link = $self->page() || '';
+    if($self->node()) {
+        my $node = $self->node();
+        $node =~ s/\|/E<verbar>/g;
+        $node =~ s{/}{E<sol>}g;
+        if($self->type() eq 'section') {
+            $link .= ($link ? '/' : '') . '"' . $node . '"';
+        }
+        elsif($self->type() eq 'hyperlink') {
+            $link = $self->node();
+        }
+        else { # item
+            $link .= '/' . $node;
+        }
+    }
+    if($self->alttext()) {
+        my $text = $self->alttext();
+        $text =~ s/\|/E<verbar>/g;
+        $text =~ s{/}{E<sol>}g;
+        $link = "$text|$link";
+    }
+    return $link;
+}
+
+sub _invalid_link {
+    my ($msg) = @_;
+    # this sets @_
+    #eval { die "$msg\n" };
+    #chomp $@;
+    $@ = $msg; # this seems to work, too!
+    return;
+}
+
+#-----------------------------------------------------------------------------
+# Pod::Cache
+#
+# class to hold POD page details
+#-----------------------------------------------------------------------------
+
+package Pod::Cache;
+
+=head2 Pod::Cache
+
+B<Pod::Cache> holds information about a set of POD documents,
+especially the nodes for hyperlinks.
+The following methods are available:
+
+=over 4
+
+=item Pod::Cache-E<gt>new()
+
+Create a new cache object. This object can hold an arbitrary number of
+POD documents of class Pod::Cache::Item.
+
+=cut
+
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my $self = [];
+    bless $self, $class;
+    return $self;
+}
+
+=item $cache-E<gt>item()
+
+Add a new item to the cache. Without arguments, this method returns a
+list of all cache elements.
+
+=cut
+
+sub item {
+    my ($self,%param) = @_;
+    if(%param) {
+        my $item = Pod::Cache::Item->new(%param);
+        push(@$self, $item);
+        return $item;
+    }
+    else {
+        return @{$self};
+    }
+}
+
+=item $cache-E<gt>find_page($name)
+
+Look for a POD document named C<$name> in the cache. Returns the
+reference to the corresponding Pod::Cache::Item object or undef if
+not found.
+
+=back
+
+=cut
+
+sub find_page {
+    my ($self,$page) = @_;
+    foreach(@$self) {
+        if($_->page() eq $page) {
+            return $_;
+        }
+    }
+    return;
+}
+
+package Pod::Cache::Item;
+
+=head2 Pod::Cache::Item
+
+B<Pod::Cache::Item> holds information about individual POD documents,
+that can be grouped in a Pod::Cache object.
+It is intended to hold information about the hyperlink nodes of POD
+documents.
+The following methods are available:
+
+=over 4
+
+=item Pod::Cache::Item-E<gt>new()
+
+Create a new object.
+
+=cut
+
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my %params = @_;
+    my $self = {%params};
+    bless $self, $class;
+    $self->initialize();
+    return $self;
+}
+
+sub initialize {
+    my $self = shift;
+    $self->{-nodes} = [] unless(defined $self->{-nodes});
+}
+
+=item $cacheitem-E<gt>page()
+
+Set/retrieve the POD document name (e.g. "Pod::Parser").
+
+=cut
+
+# The POD page
+sub page {
+   return (@_ > 1) ? ($_[0]->{-page} = $_[1]) : $_[0]->{-page};
+}
+
+=item $cacheitem-E<gt>description()
+
+Set/retrieve the POD short description as found in the C<=head1 NAME>
+section.
+
+=cut
+
+# The POD description, taken out of NAME if present
+sub description {
+   return (@_ > 1) ? ($_[0]->{-description} = $_[1]) : $_[0]->{-description};
+}
+
+=item $cacheitem-E<gt>path()
+
+Set/retrieve the POD file storage path.
+
+=cut
+
+# The file path
+sub path {
+   return (@_ > 1) ? ($_[0]->{-path} = $_[1]) : $_[0]->{-path};
+}
+
+=item $cacheitem-E<gt>file()
+
+Set/retrieve the POD file name.
+
+=cut
+
+# The POD file name
+sub file {
+   return (@_ > 1) ? ($_[0]->{-file} = $_[1]) : $_[0]->{-file};
+}
+
+=item $cacheitem-E<gt>nodes()
+
+Add a node (or a list of nodes) to the document's node list. Note that
+the order is kept, i.e. start with the first node and end with the last.
+If no argument is given, the current list of nodes is returned in the
+same order the nodes have been added.
+A node can be any scalar, but usually is a pair of node string and
+unique id for the C<find_node> method to work correctly.
+
+=cut
+
+# The POD nodes
+sub nodes {
+    my ($self,@nodes) = @_;
+    if(@nodes) {
+        push(@{$self->{-nodes}}, @nodes);
+        return @nodes;
+    }
+    else {
+        return @{$self->{-nodes}};
+    }
+}
+
+=item $cacheitem-E<gt>find_node($name)
+
+Look for a node or index entry named C<$name> in the object.
+Returns the unique id of the node (i.e. the second element of the array
+stored in the node array) or undef if not found.
+
+=cut
+
+sub find_node {
+    my ($self,$node) = @_;
+    my @search;
+    push(@search, @{$self->{-nodes}}) if($self->{-nodes});
+    push(@search, @{$self->{-idx}}) if($self->{-idx});
+    foreach(@search) {
+        if($_->[0] eq $node) {
+            return $_->[1]; # id
+        }
+    }
+    return;
+}
+
+=item $cacheitem-E<gt>idx()
+
+Add an index entry (or a list of them) to the document's index list. Note that
+the order is kept, i.e. start with the first node and end with the last.
+If no argument is given, the current list of index entries is returned in the
+same order the entries have been added.
+An index entry can be any scalar, but usually is a pair of string and
+unique id.
+
+=back
+
+=cut
+
+# The POD index entries
+sub idx {
+    my ($self,@idx) = @_;
+    if(@idx) {
+        push(@{$self->{-idx}}, @idx);
+        return @idx;
+    }
+    else {
+        return @{$self->{-idx}};
+    }
+}
+
+=head1 AUTHOR
+
+Please report bugs using L<http://rt.cpan.org>.
+
+Marek Rouchal E<lt>marekr@cpan.orgE<gt>, borrowing
+a lot of things from L<pod2man> and L<pod2roff> as well as other POD
+processing tools by Tom Christiansen, Brad Appleton and Russ Allbery.
+
+B<Pod::ParseUtils> is part of the L<Pod::Parser> distribution.
+
+=head1 SEE ALSO
+
+L<pod2man>, L<pod2roff>, L<Pod::Parser>, L<Pod::Checker>,
+L<pod2html>
+
+=cut
+
+1;
index 41c4633..f3a8619 100644 (file)
-#############################################################################\r
-# Pod/Parser.pm -- package which defines a base class for parsing POD docs.\r
-#\r
-# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.\r
-# This file is part of "PodParser". PodParser is free software;\r
-# you can redistribute it and/or modify it under the same terms\r
-# as Perl itself.\r
-#############################################################################\r
-\r
-package Pod::Parser;\r
-use strict;\r
-\r
-## These "variables" are used as local "glob aliases" for performance\r
-use vars qw($VERSION @ISA %myData %myOpts @input_stack);\r
-$VERSION = '1.61';  ## Current version of this package\r
-require  5.005;    ## requires this Perl version or later\r
-\r
-#############################################################################\r
-\r
-=head1 NAME\r
-\r
-Pod::Parser - base class for creating POD filters and translators\r
-\r
-=head1 SYNOPSIS\r
-\r
-    use Pod::Parser;\r
-\r
-    package MyParser;\r
-    @ISA = qw(Pod::Parser);\r
-\r
-    sub command { \r
-        my ($parser, $command, $paragraph, $line_num) = @_;\r
-        ## Interpret the command and its text; sample actions might be:\r
-        if ($command eq 'head1') { ... }\r
-        elsif ($command eq 'head2') { ... }\r
-        ## ... other commands and their actions\r
-        my $out_fh = $parser->output_handle();\r
-        my $expansion = $parser->interpolate($paragraph, $line_num);\r
-        print $out_fh $expansion;\r
-    }\r
-\r
-    sub verbatim { \r
-        my ($parser, $paragraph, $line_num) = @_;\r
-        ## Format verbatim paragraph; sample actions might be:\r
-        my $out_fh = $parser->output_handle();\r
-        print $out_fh $paragraph;\r
-    }\r
-\r
-    sub textblock { \r
-        my ($parser, $paragraph, $line_num) = @_;\r
-        ## Translate/Format this block of text; sample actions might be:\r
-        my $out_fh = $parser->output_handle();\r
-        my $expansion = $parser->interpolate($paragraph, $line_num);\r
-        print $out_fh $expansion;\r
-    }\r
-\r
-    sub interior_sequence { \r
-        my ($parser, $seq_command, $seq_argument) = @_;\r
-        ## Expand an interior sequence; sample actions might be:\r
-        return "*$seq_argument*"     if ($seq_command eq 'B');\r
-        return "`$seq_argument'"     if ($seq_command eq 'C');\r
-        return "_${seq_argument}_'"  if ($seq_command eq 'I');\r
-        ## ... other sequence commands and their resulting text\r
-    }\r
-\r
-    package main;\r
-\r
-    ## Create a parser object and have it parse file whose name was\r
-    ## given on the command-line (use STDIN if no files were given).\r
-    $parser = new MyParser();\r
-    $parser->parse_from_filehandle(\*STDIN)  if (@ARGV == 0);\r
-    for (@ARGV) { $parser->parse_from_file($_); }\r
-\r
-=head1 REQUIRES\r
-\r
-perl5.005, Pod::InputObjects, Exporter, Symbol, Carp\r
-\r
-=head1 EXPORTS\r
-\r
-Nothing.\r
-\r
-=head1 DESCRIPTION\r
-\r
-B<Pod::Parser> is a base class for creating POD filters and translators.\r
-It handles most of the effort involved with parsing the POD sections\r
-from an input stream, leaving subclasses free to be concerned only with\r
-performing the actual translation of text.\r
-\r
-B<Pod::Parser> parses PODs, and makes method calls to handle the various\r
-components of the POD. Subclasses of B<Pod::Parser> override these methods\r
-to translate the POD into whatever output format they desire.\r
-\r
-Note: This module is considered as legacy; modern Perl releases (5.18 and\r
-higher) are going to remove Pod::Parser from core and use L<Pod::Simple>\r
-for all things POD.\r
-\r
-=head1 QUICK OVERVIEW\r
-\r
-To create a POD filter for translating POD documentation into some other\r
-format, you create a subclass of B<Pod::Parser> which typically overrides\r
-just the base class implementation for the following methods:\r
-\r
-=over 2\r
-\r
-=item *\r
-\r
-B<command()>\r
-\r
-=item *\r
-\r
-B<verbatim()>\r
-\r
-=item *\r
-\r
-B<textblock()>\r
-\r
-=item *\r
-\r
-B<interior_sequence()>\r
-\r
-=back\r
-\r
-You may also want to override the B<begin_input()> and B<end_input()>\r
-methods for your subclass (to perform any needed per-file and/or\r
-per-document initialization or cleanup).\r
-\r
-If you need to perform any preprocessing of input before it is parsed\r
-you may want to override one or more of B<preprocess_line()> and/or\r
-B<preprocess_paragraph()>.\r
-\r
-Sometimes it may be necessary to make more than one pass over the input\r
-files. If this is the case you have several options. You can make the\r
-first pass using B<Pod::Parser> and override your methods to store the\r
-intermediate results in memory somewhere for the B<end_pod()> method to\r
-process. You could use B<Pod::Parser> for several passes with an\r
-appropriate state variable to control the operation for each pass. If\r
-your input source can't be reset to start at the beginning, you can\r
-store it in some other structure as a string or an array and have that\r
-structure implement a B<getline()> method (which is all that\r
-B<parse_from_filehandle()> uses to read input).\r
-\r
-Feel free to add any member data fields you need to keep track of things\r
-like current font, indentation, horizontal or vertical position, or\r
-whatever else you like. Be sure to read L<"PRIVATE METHODS AND DATA">\r
-to avoid name collisions.\r
-\r
-For the most part, the B<Pod::Parser> base class should be able to\r
-do most of the input parsing for you and leave you free to worry about\r
-how to interpret the commands and translate the result.\r
-\r
-Note that all we have described here in this quick overview is the\r
-simplest most straightforward use of B<Pod::Parser> to do stream-based\r
-parsing. It is also possible to use the B<Pod::Parser::parse_text> function\r
-to do more sophisticated tree-based parsing. See L<"TREE-BASED PARSING">.\r
-\r
-=head1 PARSING OPTIONS\r
-\r
-A I<parse-option> is simply a named option of B<Pod::Parser> with a\r
-value that corresponds to a certain specified behavior. These various\r
-behaviors of B<Pod::Parser> may be enabled/disabled by setting\r
-or unsetting one or more I<parse-options> using the B<parseopts()> method.\r
-The set of currently accepted parse-options is as follows:\r
-\r
-=over 3\r
-\r
-=item B<-want_nonPODs> (default: unset)\r
-\r
-Normally (by default) B<Pod::Parser> will only provide access to\r
-the POD sections of the input. Input paragraphs that are not part\r
-of the POD-format documentation are not made available to the caller\r
-(not even using B<preprocess_paragraph()>). Setting this option to a\r
-non-empty, non-zero value will allow B<preprocess_paragraph()> to see\r
-non-POD sections of the input as well as POD sections. The B<cutting()>\r
-method can be used to determine if the corresponding paragraph is a POD\r
-paragraph, or some other input paragraph.\r
-\r
-=item B<-process_cut_cmd> (default: unset)\r
-\r
-Normally (by default) B<Pod::Parser> handles the C<=cut> POD directive\r
-by itself and does not pass it on to the caller for processing. Setting\r
-this option to a non-empty, non-zero value will cause B<Pod::Parser> to\r
-pass the C<=cut> directive to the caller just like any other POD command\r
-(and hence it may be processed by the B<command()> method).\r
-\r
-B<Pod::Parser> will still interpret the C<=cut> directive to mean that\r
-"cutting mode" has been (re)entered, but the caller will get a chance\r
-to capture the actual C<=cut> paragraph itself for whatever purpose\r
-it desires.\r
-\r
-=item B<-warnings> (default: unset)\r
-\r
-Normally (by default) B<Pod::Parser> recognizes a bare minimum of\r
-pod syntax errors and warnings and issues diagnostic messages\r
-for errors, but not for warnings. (Use B<Pod::Checker> to do more\r
-thorough checking of POD syntax.) Setting this option to a non-empty,\r
-non-zero value will cause B<Pod::Parser> to issue diagnostics for\r
-the few warnings it recognizes as well as the errors.\r
-\r
-=back\r
-\r
-Please see L<"parseopts()"> for a complete description of the interface\r
-for the setting and unsetting of parse-options.\r
-\r
-=cut\r
-\r
-#############################################################################\r
-\r
-#use diagnostics;\r
-use Pod::InputObjects;\r
-use Carp;\r
-use Exporter;\r
-BEGIN {\r
-   if ($] < 5.006) {\r
-      require Symbol;\r
-      import Symbol;\r
-   }\r
-}\r
-@ISA = qw(Exporter);\r
-\r
-#############################################################################\r
-\r
-=head1 RECOMMENDED SUBROUTINE/METHOD OVERRIDES\r
-\r
-B<Pod::Parser> provides several methods which most subclasses will probably\r
-want to override. These methods are as follows:\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<command()>\r
-\r
-            $parser->command($cmd,$text,$line_num,$pod_para);\r
-\r
-This method should be overridden by subclasses to take the appropriate\r
-action when a POD command paragraph (denoted by a line beginning with\r
-"=") is encountered. When such a POD directive is seen in the input,\r
-this method is called and is passed:\r
-\r
-=over 3\r
-\r
-=item C<$cmd>\r
-\r
-the name of the command for this POD paragraph\r
-\r
-=item C<$text>\r
-\r
-the paragraph text for the given POD paragraph command.\r
-\r
-=item C<$line_num>\r
-\r
-the line-number of the beginning of the paragraph\r
-\r
-=item C<$pod_para>\r
-\r
-a reference to a C<Pod::Paragraph> object which contains further\r
-information about the paragraph command (see L<Pod::InputObjects>\r
-for details).\r
-\r
-=back\r
-\r
-B<Note> that this method I<is> called for C<=pod> paragraphs.\r
-\r
-The base class implementation of this method simply treats the raw POD\r
-command as normal block of paragraph text (invoking the B<textblock()>\r
-method with the command paragraph).\r
-\r
-=cut\r
-\r
-sub command {\r
-    my ($self, $cmd, $text, $line_num, $pod_para)  = @_;\r
-    ## Just treat this like a textblock\r
-    $self->textblock($pod_para->raw_text(), $line_num, $pod_para);\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<verbatim()>\r
-\r
-            $parser->verbatim($text,$line_num,$pod_para);\r
-\r
-This method may be overridden by subclasses to take the appropriate\r
-action when a block of verbatim text is encountered. It is passed the\r
-following parameters:\r
-\r
-=over 3\r
-\r
-=item C<$text>\r
-\r
-the block of text for the verbatim paragraph\r
-\r
-=item C<$line_num>\r
-\r
-the line-number of the beginning of the paragraph\r
-\r
-=item C<$pod_para>\r
-\r
-a reference to a C<Pod::Paragraph> object which contains further\r
-information about the paragraph (see L<Pod::InputObjects>\r
-for details).\r
-\r
-=back\r
-\r
-The base class implementation of this method simply prints the textblock\r
-(unmodified) to the output filehandle.\r
-\r
-=cut\r
-\r
-sub verbatim {\r
-    my ($self, $text, $line_num, $pod_para) = @_;\r
-    my $out_fh = $self->{_OUTPUT};\r
-    print $out_fh $text;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<textblock()>\r
-\r
-            $parser->textblock($text,$line_num,$pod_para);\r
-\r
-This method may be overridden by subclasses to take the appropriate\r
-action when a normal block of POD text is encountered (although the base\r
-class method will usually do what you want). It is passed the following\r
-parameters:\r
-\r
-=over 3\r
-\r
-=item C<$text>\r
-\r
-the block of text for the a POD paragraph\r
-\r
-=item C<$line_num>\r
-\r
-the line-number of the beginning of the paragraph\r
-\r
-=item C<$pod_para>\r
-\r
-a reference to a C<Pod::Paragraph> object which contains further\r
-information about the paragraph (see L<Pod::InputObjects>\r
-for details).\r
-\r
-=back\r
-\r
-In order to process interior sequences, subclasses implementations of\r
-this method will probably want to invoke either B<interpolate()> or\r
-B<parse_text()>, passing it the text block C<$text>, and the corresponding\r
-line number in C<$line_num>, and then perform any desired processing upon\r
-the returned result.\r
-\r
-The base class implementation of this method simply prints the text block\r
-as it occurred in the input stream).\r
-\r
-=cut\r
-\r
-sub textblock {\r
-    my ($self, $text, $line_num, $pod_para) = @_;\r
-    my $out_fh = $self->{_OUTPUT};\r
-    print $out_fh $self->interpolate($text, $line_num);\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<interior_sequence()>\r
-\r
-            $parser->interior_sequence($seq_cmd,$seq_arg,$pod_seq);\r
-\r
-This method should be overridden by subclasses to take the appropriate\r
-action when an interior sequence is encountered. An interior sequence is\r
-an embedded command within a block of text which appears as a command\r
-name (usually a single uppercase character) followed immediately by a\r
-string of text which is enclosed in angle brackets. This method is\r
-passed the sequence command C<$seq_cmd> and the corresponding text\r
-C<$seq_arg>. It is invoked by the B<interpolate()> method for each interior\r
-sequence that occurs in the string that it is passed. It should return\r
-the desired text string to be used in place of the interior sequence.\r
-The C<$pod_seq> argument is a reference to a C<Pod::InteriorSequence>\r
-object which contains further information about the interior sequence.\r
-Please see L<Pod::InputObjects> for details if you need to access this\r
-additional information.\r
-\r
-Subclass implementations of this method may wish to invoke the \r
-B<nested()> method of C<$pod_seq> to see if it is nested inside\r
-some other interior-sequence (and if so, which kind).\r
-\r
-The base class implementation of the B<interior_sequence()> method\r
-simply returns the raw text of the interior sequence (as it occurred\r
-in the input) to the caller.\r
-\r
-=cut\r
-\r
-sub interior_sequence {\r
-    my ($self, $seq_cmd, $seq_arg, $pod_seq) = @_;\r
-    ## Just return the raw text of the interior sequence\r
-    return  $pod_seq->raw_text();\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 OPTIONAL SUBROUTINE/METHOD OVERRIDES\r
-\r
-B<Pod::Parser> provides several methods which subclasses may want to override\r
-to perform any special pre/post-processing. These methods do I<not> have to\r
-be overridden, but it may be useful for subclasses to take advantage of them.\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<new()>\r
-\r
-            my $parser = Pod::Parser->new();\r
-\r
-This is the constructor for B<Pod::Parser> and its subclasses. You\r
-I<do not> need to override this method! It is capable of constructing\r
-subclass objects as well as base class objects, provided you use\r
-any of the following constructor invocation styles:\r
-\r
-    my $parser1 = MyParser->new();\r
-    my $parser2 = new MyParser();\r
-    my $parser3 = $parser2->new();\r
-\r
-where C<MyParser> is some subclass of B<Pod::Parser>.\r
-\r
-Using the syntax C<MyParser::new()> to invoke the constructor is I<not>\r
-recommended, but if you insist on being able to do this, then the\r
-subclass I<will> need to override the B<new()> constructor method. If\r
-you do override the constructor, you I<must> be sure to invoke the\r
-B<initialize()> method of the newly blessed object.\r
-\r
-Using any of the above invocations, the first argument to the\r
-constructor is always the corresponding package name (or object\r
-reference). No other arguments are required, but if desired, an\r
-associative array (or hash-table) my be passed to the B<new()>\r
-constructor, as in:\r
-\r
-    my $parser1 = MyParser->new( MYDATA => $value1, MOREDATA => $value2 );\r
-    my $parser2 = new MyParser( -myflag => 1 );\r
-\r
-All arguments passed to the B<new()> constructor will be treated as\r
-key/value pairs in a hash-table. The newly constructed object will be\r
-initialized by copying the contents of the given hash-table (which may\r
-have been empty). The B<new()> constructor for this class and all of its\r
-subclasses returns a blessed reference to the initialized object (hash-table).\r
-\r
-=cut\r
-\r
-sub new {\r
-    ## Determine if we were called via an object-ref or a classname\r
-    my ($this,%params) = @_;\r
-    my $class = ref($this) || $this;\r
-    ## Any remaining arguments are treated as initial values for the\r
-    ## hash that is used to represent this object.\r
-    my $self = { %params };\r
-    ## Bless ourselves into the desired class and perform any initialization\r
-    bless $self, $class;\r
-    $self->initialize();\r
-    return $self;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<initialize()>\r
-\r
-            $parser->initialize();\r
-\r
-This method performs any necessary object initialization. It takes no\r
-arguments (other than the object instance of course, which is typically\r
-copied to a local variable named C<$self>). If subclasses override this\r
-method then they I<must> be sure to invoke C<$self-E<gt>SUPER::initialize()>.\r
-\r
-=cut\r
-\r
-sub initialize {\r
-    #my $self = shift;\r
-    #return;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<begin_pod()>\r
-\r
-            $parser->begin_pod();\r
-\r
-This method is invoked at the beginning of processing for each POD\r
-document that is encountered in the input. Subclasses should override\r
-this method to perform any per-document initialization.\r
-\r
-=cut\r
-\r
-sub begin_pod {\r
-    #my $self = shift;\r
-    #return;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<begin_input()>\r
-\r
-            $parser->begin_input();\r
-\r
-This method is invoked by B<parse_from_filehandle()> immediately I<before>\r
-processing input from a filehandle. The base class implementation does\r
-nothing, however, subclasses may override it to perform any per-file\r
-initializations.\r
-\r
-Note that if multiple files are parsed for a single POD document\r
-(perhaps the result of some future C<=include> directive) this method\r
-is invoked for every file that is parsed. If you wish to perform certain\r
-initializations once per document, then you should use B<begin_pod()>.\r
-\r
-=cut\r
-\r
-sub begin_input {\r
-    #my $self = shift;\r
-    #return;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<end_input()>\r
-\r
-            $parser->end_input();\r
-\r
-This method is invoked by B<parse_from_filehandle()> immediately I<after>\r
-processing input from a filehandle. The base class implementation does\r
-nothing, however, subclasses may override it to perform any per-file\r
-cleanup actions.\r
-\r
-Please note that if multiple files are parsed for a single POD document\r
-(perhaps the result of some kind of C<=include> directive) this method\r
-is invoked for every file that is parsed. If you wish to perform certain\r
-cleanup actions once per document, then you should use B<end_pod()>.\r
-\r
-=cut\r
-\r
-sub end_input {\r
-    #my $self = shift;\r
-    #return;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<end_pod()>\r
-\r
-            $parser->end_pod();\r
-\r
-This method is invoked at the end of processing for each POD document\r
-that is encountered in the input. Subclasses should override this method\r
-to perform any per-document finalization.\r
-\r
-=cut\r
-\r
-sub end_pod {\r
-    #my $self = shift;\r
-    #return;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<preprocess_line()>\r
-\r
-          $textline = $parser->preprocess_line($text, $line_num);\r
-\r
-This method should be overridden by subclasses that wish to perform\r
-any kind of preprocessing for each I<line> of input (I<before> it has\r
-been determined whether or not it is part of a POD paragraph). The\r
-parameter C<$text> is the input line; and the parameter C<$line_num> is\r
-the line number of the corresponding text line.\r
-\r
-The value returned should correspond to the new text to use in its\r
-place.  If the empty string or an undefined value is returned then no\r
-further processing will be performed for this line.\r
-\r
-Please note that the B<preprocess_line()> method is invoked I<before>\r
-the B<preprocess_paragraph()> method. After all (possibly preprocessed)\r
-lines in a paragraph have been assembled together and it has been\r
-determined that the paragraph is part of the POD documentation from one\r
-of the selected sections, then B<preprocess_paragraph()> is invoked.\r
-\r
-The base class implementation of this method returns the given text.\r
-\r
-=cut\r
-\r
-sub preprocess_line {\r
-    my ($self, $text, $line_num) = @_;\r
-    return  $text;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<preprocess_paragraph()>\r
-\r
-            $textblock = $parser->preprocess_paragraph($text, $line_num);\r
-\r
-This method should be overridden by subclasses that wish to perform any\r
-kind of preprocessing for each block (paragraph) of POD documentation\r
-that appears in the input stream. The parameter C<$text> is the POD\r
-paragraph from the input file; and the parameter C<$line_num> is the\r
-line number for the beginning of the corresponding paragraph.\r
-\r
-The value returned should correspond to the new text to use in its\r
-place If the empty string is returned or an undefined value is\r
-returned, then the given C<$text> is ignored (not processed).\r
-\r
-This method is invoked after gathering up all the lines in a paragraph\r
-and after determining the cutting state of the paragraph,\r
-but before trying to further parse or interpret them. After\r
-B<preprocess_paragraph()> returns, the current cutting state (which\r
-is returned by C<$self-E<gt>cutting()>) is examined. If it evaluates\r
-to true then input text (including the given C<$text>) is cut (not\r
-processed) until the next POD directive is encountered.\r
-\r
-Please note that the B<preprocess_line()> method is invoked I<before>\r
-the B<preprocess_paragraph()> method. After all (possibly preprocessed)\r
-lines in a paragraph have been assembled together and either it has been\r
-determined that the paragraph is part of the POD documentation from one\r
-of the selected sections or the C<-want_nonPODs> option is true,\r
-then B<preprocess_paragraph()> is invoked.\r
-\r
-The base class implementation of this method returns the given text.\r
-\r
-=cut\r
-\r
-sub preprocess_paragraph {\r
-    my ($self, $text, $line_num) = @_;\r
-    return  $text;\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 METHODS FOR PARSING AND PROCESSING\r
-\r
-B<Pod::Parser> provides several methods to process input text. These\r
-methods typically won't need to be overridden (and in some cases they\r
-can't be overridden), but subclasses may want to invoke them to exploit\r
-their functionality.\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<parse_text()>\r
-\r
-            $ptree1 = $parser->parse_text($text, $line_num);\r
-            $ptree2 = $parser->parse_text({%opts}, $text, $line_num);\r
-            $ptree3 = $parser->parse_text(\%opts, $text, $line_num);\r
-\r
-This method is useful if you need to perform your own interpolation \r
-of interior sequences and can't rely upon B<interpolate> to expand\r
-them in simple bottom-up order.\r
-\r
-The parameter C<$text> is a string or block of text to be parsed\r
-for interior sequences; and the parameter C<$line_num> is the\r
-line number corresponding to the beginning of C<$text>.\r
-\r
-B<parse_text()> will parse the given text into a parse-tree of "nodes."\r
-and interior-sequences.  Each "node" in the parse tree is either a\r
-text-string, or a B<Pod::InteriorSequence>.  The result returned is a\r
-parse-tree of type B<Pod::ParseTree>. Please see L<Pod::InputObjects>\r
-for more information about B<Pod::InteriorSequence> and B<Pod::ParseTree>.\r
-\r
-If desired, an optional hash-ref may be specified as the first argument\r
-to customize certain aspects of the parse-tree that is created and\r
-returned. The set of recognized option keywords are:\r
-\r
-=over 3\r
-\r
-=item B<-expand_seq> =E<gt> I<code-ref>|I<method-name>\r
-\r
-Normally, the parse-tree returned by B<parse_text()> will contain an\r
-unexpanded C<Pod::InteriorSequence> object for each interior-sequence\r
-encountered. Specifying B<-expand_seq> tells B<parse_text()> to "expand"\r
-every interior-sequence it sees by invoking the referenced function\r
-(or named method of the parser object) and using the return value as the\r
-expanded result.\r
-\r
-If a subroutine reference was given, it is invoked as:\r
-\r
-  &$code_ref( $parser, $sequence )\r
-\r
-and if a method-name was given, it is invoked as:\r
-\r
-  $parser->method_name( $sequence )\r
-\r
-where C<$parser> is a reference to the parser object, and C<$sequence>\r
-is a reference to the interior-sequence object.\r
-[I<NOTE>: If the B<interior_sequence()> method is specified, then it is\r
-invoked according to the interface specified in L<"interior_sequence()">].\r
-\r
-=item B<-expand_text> =E<gt> I<code-ref>|I<method-name>\r
-\r
-Normally, the parse-tree returned by B<parse_text()> will contain a\r
-text-string for each contiguous sequence of characters outside of an\r
-interior-sequence. Specifying B<-expand_text> tells B<parse_text()> to\r
-"preprocess" every such text-string it sees by invoking the referenced\r
-function (or named method of the parser object) and using the return value\r
-as the preprocessed (or "expanded") result. [Note that if the result is\r
-an interior-sequence, then it will I<not> be expanded as specified by the\r
-B<-expand_seq> option; Any such recursive expansion needs to be handled by\r
-the specified callback routine.]\r
-\r
-If a subroutine reference was given, it is invoked as:\r
-\r
-  &$code_ref( $parser, $text, $ptree_node )\r
-\r
-and if a method-name was given, it is invoked as:\r
-\r
-  $parser->method_name( $text, $ptree_node )\r
-\r
-where C<$parser> is a reference to the parser object, C<$text> is the\r
-text-string encountered, and C<$ptree_node> is a reference to the current\r
-node in the parse-tree (usually an interior-sequence object or else the\r
-top-level node of the parse-tree).\r
-\r
-=item B<-expand_ptree> =E<gt> I<code-ref>|I<method-name>\r
-\r
-Rather than returning a C<Pod::ParseTree>, pass the parse-tree as an\r
-argument to the referenced subroutine (or named method of the parser\r
-object) and return the result instead of the parse-tree object.\r
-\r
-If a subroutine reference was given, it is invoked as:\r
-\r
-  &$code_ref( $parser, $ptree )\r
-\r
-and if a method-name was given, it is invoked as:\r
-\r
-  $parser->method_name( $ptree )\r
-\r
-where C<$parser> is a reference to the parser object, and C<$ptree>\r
-is a reference to the parse-tree object.\r
-\r
-=back\r
-\r
-=cut\r
-\r
-sub parse_text {\r
-    my $self = shift;\r
-    local $_ = '';\r
-\r
-    ## Get options and set any defaults\r
-    my %opts = (ref $_[0]) ? %{ shift() } : ();\r
-    my $expand_seq   = $opts{'-expand_seq'}   || undef;\r
-    my $expand_text  = $opts{'-expand_text'}  || undef;\r
-    my $expand_ptree = $opts{'-expand_ptree'} || undef;\r
-\r
-    my $text = shift;\r
-    my $line = shift;\r
-    my $file = $self->input_file();\r
-    my $cmd  = "";\r
-\r
-    ## Convert method calls into closures, for our convenience\r
-    my $xseq_sub   = $expand_seq;\r
-    my $xtext_sub  = $expand_text;\r
-    my $xptree_sub = $expand_ptree;\r
-    if (defined $expand_seq  and  $expand_seq eq 'interior_sequence') {\r
-        ## If 'interior_sequence' is the method to use, we have to pass\r
-        ## more than just the sequence object, we also need to pass the\r
-        ## sequence name and text.\r
-        $xseq_sub = sub {\r
-            my ($sself, $iseq) = @_;\r
-            my $args = join('', $iseq->parse_tree->children);\r
-            return  $sself->interior_sequence($iseq->name, $args, $iseq);\r
-        };\r
-    }\r
-    ref $xseq_sub    or  $xseq_sub   = sub { shift()->$expand_seq(@_) };\r
-    ref $xtext_sub   or  $xtext_sub  = sub { shift()->$expand_text(@_) };\r
-    ref $xptree_sub  or  $xptree_sub = sub { shift()->$expand_ptree(@_) };\r
-\r
-    ## Keep track of the "current" interior sequence, and maintain a stack\r
-    ## of "in progress" sequences.\r
-    ##\r
-    ## NOTE that we push our own "accumulator" at the very beginning of the\r
-    ## stack. It's really a parse-tree, not a sequence; but it implements\r
-    ## the methods we need so we can use it to gather-up all the sequences\r
-    ## and strings we parse. Thus, by the end of our parsing, it should be\r
-    ## the only thing left on our stack and all we have to do is return it!\r
-    ##\r
-    my $seq       = Pod::ParseTree->new();\r
-    my @seq_stack = ($seq);\r
-    my ($ldelim, $rdelim) = ('', '');\r
-\r
-    ## Iterate over all sequence starts text (NOTE: split with\r
-    ## capturing parens keeps the delimiters)\r
-    $_ = $text;\r
-    my @tokens = split /([A-Z]<(?:<+(?:\r?\n|[ \t]))?)/;\r
-    while ( @tokens ) {\r
-        $_ = shift @tokens;\r
-        ## Look for the beginning of a sequence\r
-        if ( /^([A-Z])(<(?:<+(?:\r?\n|[ \t]))?)$/ ) {\r
-            ## Push a new sequence onto the stack of those "in-progress"\r
-            my $ldelim_orig;\r
-            ($cmd, $ldelim_orig) = ($1, $2);\r
-            ($ldelim = $ldelim_orig) =~ s/\s+$//;\r
-            ($rdelim = $ldelim) =~ tr/</>/;\r
-            $seq = Pod::InteriorSequence->new(\r
-                       -name   => $cmd,\r
-                       -ldelim => $ldelim_orig,  -rdelim => $rdelim,\r
-                       -file   => $file,    -line   => $line\r
-                   );\r
-            (@seq_stack > 1)  and  $seq->nested($seq_stack[-1]);\r
-            push @seq_stack, $seq;\r
-        }\r
-        ## Look for sequence ending\r
-        elsif ( @seq_stack > 1 ) {\r
-            ## Make sure we match the right kind of closing delimiter\r
-            my ($seq_end, $post_seq) = ('', '');\r
-            if ( ($ldelim eq '<'   and  /\A(.*?)(>)/s)\r
-                 or  /\A(.*?)(\s+$rdelim)/s )\r
-            {\r
-                ## Found end-of-sequence, capture the interior and the\r
-                ## closing the delimiter, and put the rest back on the\r
-                ## token-list\r
-                $post_seq = substr($_, length($1) + length($2));\r
-                ($_, $seq_end) = ($1, $2);\r
-                (length $post_seq)  and  unshift @tokens, $post_seq;\r
-            }\r
-            if (length) {\r
-                ## In the middle of a sequence, append this text to it, and\r
-                ## don't forget to "expand" it if that's what the caller wanted\r
-                $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);\r
-                $_ .= $seq_end;\r
-            }\r
-            if (length $seq_end) {\r
-                ## End of current sequence, record terminating delimiter\r
-                $seq->rdelim($seq_end);\r
-                ## Pop it off the stack of "in progress" sequences\r
-                pop @seq_stack;\r
-                ## Append result to its parent in current parse tree\r
-                $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq)\r
-                                                   : $seq);\r
-                ## Remember the current cmd-name and left-delimiter\r
-                if(@seq_stack > 1) {\r
-                    $cmd = $seq_stack[-1]->name;\r
-                    $ldelim = $seq_stack[-1]->ldelim;\r
-                    $rdelim = $seq_stack[-1]->rdelim;\r
-                } else {\r
-                    $cmd = $ldelim = $rdelim = '';\r
-                }\r
-            }\r
-        }\r
-        elsif (length) {\r
-            ## In the middle of a sequence, append this text to it, and\r
-            ## don't forget to "expand" it if that's what the caller wanted\r
-            $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);\r
-        }\r
-        ## Keep track of line count\r
-        $line += /\n/;\r
-        ## Remember the "current" sequence\r
-        $seq = $seq_stack[-1];\r
-    }\r
-\r
-    ## Handle unterminated sequences\r
-    my $errorsub = (@seq_stack > 1) ? $self->errorsub() : undef;\r
-    while (@seq_stack > 1) {\r
-       ($cmd, $file, $line) = ($seq->name, $seq->file_line);\r
-       $ldelim  = $seq->ldelim;\r
-       ($rdelim = $ldelim) =~ tr/</>/;\r
-       $rdelim  =~ s/^(\S+)(\s*)$/$2$1/;\r
-       pop @seq_stack;\r
-       my $errmsg = "*** ERROR: unterminated ${cmd}${ldelim}...${rdelim}".\r
-                    " at line $line in file $file\n";\r
-       (ref $errorsub) and &{$errorsub}($errmsg)\r
-           or (defined $errorsub) and $self->$errorsub($errmsg)\r
-               or  carp($errmsg);\r
-       $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq) : $seq);\r
-       $seq = $seq_stack[-1];\r
-    }\r
-\r
-    ## Return the resulting parse-tree\r
-    my $ptree = (pop @seq_stack)->parse_tree;\r
-    return  $expand_ptree ? &$xptree_sub($self, $ptree) : $ptree;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<interpolate()>\r
-\r
-            $textblock = $parser->interpolate($text, $line_num);\r
-\r
-This method translates all text (including any embedded interior sequences)\r
-in the given text string C<$text> and returns the interpolated result. The\r
-parameter C<$line_num> is the line number corresponding to the beginning\r
-of C<$text>.\r
-\r
-B<interpolate()> merely invokes a private method to recursively expand\r
-nested interior sequences in bottom-up order (innermost sequences are\r
-expanded first). If there is a need to expand nested sequences in\r
-some alternate order, use B<parse_text> instead.\r
-\r
-=cut\r
-\r
-sub interpolate {\r
-    my($self, $text, $line_num) = @_;\r
-    my %parse_opts = ( -expand_seq => 'interior_sequence' );\r
-    my $ptree = $self->parse_text( \%parse_opts, $text, $line_num );\r
-    return  join '', $ptree->children();\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head1 B<parse_paragraph()>\r
-\r
-            $parser->parse_paragraph($text, $line_num);\r
-\r
-This method takes the text of a POD paragraph to be processed, along\r
-with its corresponding line number, and invokes the appropriate method\r
-(one of B<command()>, B<verbatim()>, or B<textblock()>).\r
-\r
-For performance reasons, this method is invoked directly without any\r
-dynamic lookup; Hence subclasses may I<not> override it!\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub parse_paragraph {\r
-    my ($self, $text, $line_num) = @_;\r
-    local *myData = $self;  ## alias to avoid deref-ing overhead\r
-    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options\r
-    local $_;\r
-\r
-    ## See if we want to preprocess nonPOD paragraphs as well as POD ones.\r
-    my $wantNonPods = $myOpts{'-want_nonPODs'};\r
-\r
-    ## Update cutting status\r
-    $myData{_CUTTING} = 0 if $text =~ /^={1,2}\S/;\r
-\r
-    ## Perform any desired preprocessing if we wanted it this early\r
-    $wantNonPods  and  $text = $self->preprocess_paragraph($text, $line_num);\r
-\r
-    ## Ignore up until next POD directive if we are cutting\r
-    return if $myData{_CUTTING};\r
-\r
-    ## Now we know this is block of text in a POD section!\r
-\r
-    ##-----------------------------------------------------------------\r
-    ## This is a hook (hack ;-) for Pod::Select to do its thing without\r
-    ## having to override methods, but also without Pod::Parser assuming\r
-    ## $self is an instance of Pod::Select (if the _SELECTED_SECTIONS\r
-    ## field exists then we assume there is an is_selected() method for\r
-    ## us to invoke (calling $self->can('is_selected') could verify this\r
-    ## but that is more overhead than I want to incur)\r
-    ##-----------------------------------------------------------------\r
-\r
-    ## Ignore this block if it isn't in one of the selected sections\r
-    if (exists $myData{_SELECTED_SECTIONS}) {\r
-        $self->is_selected($text)  or  return ($myData{_CUTTING} = 1);\r
-    }\r
-\r
-    ## If we haven't already, perform any desired preprocessing and\r
-    ## then re-check the "cutting" state\r
-    unless ($wantNonPods) {\r
-       $text = $self->preprocess_paragraph($text, $line_num);\r
-       return 1  unless ((defined $text) and (length $text));\r
-       return 1  if ($myData{_CUTTING});\r
-    }\r
-\r
-    ## Look for one of the three types of paragraphs\r
-    my ($pfx, $cmd, $arg, $sep) = ('', '', '', '');\r
-    my $pod_para = undef;\r
-    if ($text =~ /^(={1,2})(?=\S)/) {\r
-        ## Looks like a command paragraph. Capture the command prefix used\r
-        ## ("=" or "=="), as well as the command-name, its paragraph text,\r
-        ## and whatever sequence of characters was used to separate them\r
-        $pfx = $1;\r
-        $_ = substr($text, length $pfx);\r
-        ($cmd, $sep, $text) = split /(\s+)/, $_, 2;\r
-        $sep = '' unless defined $sep;\r
-        $text = '' unless defined $text;\r
-        ## If this is a "cut" directive then we don't need to do anything\r
-        ## except return to "cutting" mode.\r
-        if ($cmd eq 'cut') {\r
-           $myData{_CUTTING} = 1;\r
-           return  unless $myOpts{'-process_cut_cmd'};\r
-        }\r
-    }\r
-    ## Save the attributes indicating how the command was specified.\r
-    $pod_para = new Pod::Paragraph(\r
-          -name      => $cmd,\r
-          -text      => $text,\r
-          -prefix    => $pfx,\r
-          -separator => $sep,\r
-          -file      => $myData{_INFILE},\r
-          -line      => $line_num\r
-    );\r
-    # ## Invoke appropriate callbacks\r
-    # if (exists $myData{_CALLBACKS}) {\r
-    #    ## Look through the callback list, invoke callbacks,\r
-    #    ## then see if we need to do the default actions\r
-    #    ## (invoke_callbacks will return true if we do).\r
-    #    return  1  unless $self->invoke_callbacks($cmd, $text, $line_num, $pod_para);\r
-    # }\r
-\r
-    # If the last paragraph ended in whitespace, and we're not between verbatim blocks, carp\r
-    if ($myData{_WHITESPACE} and $myOpts{'-warnings'}\r
-            and not ($text =~ /^\s+/ and ($myData{_PREVIOUS}||"") eq "verbatim")) {\r
-        my $errorsub = $self->errorsub();\r
-        my $line = $line_num - 1;\r
-        my $errmsg = "*** WARNING: line containing nothing but whitespace".\r
-                     " in paragraph at line $line in file $myData{_INFILE}\n";\r
-        (ref $errorsub) and &{$errorsub}($errmsg)\r
-            or (defined $errorsub) and $self->$errorsub($errmsg)\r
-                or  carp($errmsg);\r
-    }\r
-\r
-    if (length $cmd) {\r
-        ## A command paragraph\r
-        $self->command($cmd, $text, $line_num, $pod_para);\r
-        $myData{_PREVIOUS} = $cmd;\r
-    }\r
-    elsif ($text =~ /^\s+/) {\r
-        ## Indented text - must be a verbatim paragraph\r
-        $self->verbatim($text, $line_num, $pod_para);\r
-        $myData{_PREVIOUS} = "verbatim";\r
-    }\r
-    else {\r
-        ## Looks like an ordinary block of text\r
-        $self->textblock($text, $line_num, $pod_para);\r
-        $myData{_PREVIOUS} = "textblock";\r
-    }\r
-\r
-    # Update the whitespace for the next time around\r
-    #$myData{_WHITESPACE} = $text =~ /^[^\S\r\n]+\Z/m ? 1 : 0;\r
-    $myData{_WHITESPACE} = $text =~ /^[^\S\r\n]+\r*\Z/m ? 1 : 0;\r
-\r
-    return  1;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<parse_from_filehandle()>\r
-\r
-            $parser->parse_from_filehandle($in_fh,$out_fh);\r
-\r
-This method takes an input filehandle (which is assumed to already be\r
-opened for reading) and reads the entire input stream looking for blocks\r
-(paragraphs) of POD documentation to be processed. If no first argument\r
-is given the default input filehandle C<STDIN> is used.\r
-\r
-The C<$in_fh> parameter may be any object that provides a B<getline()>\r
-method to retrieve a single line of input text (hence, an appropriate\r
-wrapper object could be used to parse PODs from a single string or an\r
-array of strings).\r
-\r
-Using C<$in_fh-E<gt>getline()>, input is read line-by-line and assembled\r
-into paragraphs or "blocks" (which are separated by lines containing\r
-nothing but whitespace). For each block of POD documentation\r
-encountered it will invoke a method to parse the given paragraph.\r
-\r
-If a second argument is given then it should correspond to a filehandle where\r
-output should be sent (otherwise the default output filehandle is\r
-C<STDOUT> if no output filehandle is currently in use).\r
-\r
-B<NOTE:> For performance reasons, this method caches the input stream at\r
-the top of the stack in a local variable. Any attempts by clients to\r
-change the stack contents during processing when in the midst executing\r
-of this method I<will not affect> the input stream used by the current\r
-invocation of this method.\r
-\r
-This method does I<not> usually need to be overridden by subclasses.\r
-\r
-=cut\r
-\r
-sub parse_from_filehandle {\r
-    my $self = shift;\r
-    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();\r
-    my ($in_fh, $out_fh) = @_;\r
-    $in_fh = \*STDIN  unless ($in_fh);\r
-    local *myData = $self;  ## alias to avoid deref-ing overhead\r
-    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options\r
-    local $_;\r
-\r
-    ## Put this stream at the top of the stack and do beginning-of-input\r
-    ## processing. NOTE that $in_fh might be reset during this process.\r
-    my $topstream = $self->_push_input_stream($in_fh, $out_fh);\r
-    (exists $opts{-cutting})  and  $self->cutting( $opts{-cutting} );\r
-\r
-    ## Initialize line/paragraph\r
-    my ($textline, $paragraph) = ('', '');\r
-    my ($nlines, $plines) = (0, 0);\r
-\r
-    ## Use <$fh> instead of $fh->getline where possible (for speed)\r
-    $_ = ref $in_fh;\r
-    my $tied_fh = (/^(?:GLOB|FileHandle|IO::\w+)$/  or  tied $in_fh);\r
-\r
-    ## Read paragraphs line-by-line\r
-    while (defined ($textline = $tied_fh ? <$in_fh> : $in_fh->getline)) {\r
-        $textline = $self->preprocess_line($textline, ++$nlines);\r
-        next  unless ((defined $textline)  &&  (length $textline));\r
-\r
-        if ((! length $paragraph) && ($textline =~ /^==/)) {\r
-            ## '==' denotes a one-line command paragraph\r
-            $paragraph = $textline;\r
-            $plines    = 1;\r
-            $textline  = '';\r
-        } else {\r
-            ## Append this line to the current paragraph\r
-            $paragraph .= $textline;\r
-            ++$plines;\r
-        }\r
-\r
-        ## See if this line is blank and ends the current paragraph.\r
-        ## If it isn't, then keep iterating until it is.\r
-        next unless (($textline =~ /^[^\S\r\n]*[\r\n]*$/)\r
-                                     && (length $paragraph));\r
-\r
-        ## Now process the paragraph\r
-        parse_paragraph($self, $paragraph, ($nlines - $plines) + 1);\r
-        $paragraph = '';\r
-        $plines = 0;\r
-    }\r
-    ## Don't forget about the last paragraph in the file\r
-    if (length $paragraph) {\r
-       parse_paragraph($self, $paragraph, ($nlines - $plines) + 1)\r
-    }\r
-\r
-    ## Now pop the input stream off the top of the input stack.\r
-    $self->_pop_input_stream();\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<parse_from_file()>\r
-\r
-            $parser->parse_from_file($filename,$outfile);\r
-\r
-This method takes a filename and does the following:\r
-\r
-=over 2\r
-\r
-=item *\r
-\r
-opens the input and output files for reading\r
-(creating the appropriate filehandles)\r
-\r
-=item *\r
-\r
-invokes the B<parse_from_filehandle()> method passing it the\r
-corresponding input and output filehandles.\r
-\r
-=item *\r
-\r
-closes the input and output files.\r
-\r
-=back\r
-\r
-If the special input filename "-" or "<&STDIN" is given then the STDIN\r
-filehandle is used for input (and no open or close is performed). If no\r
-input filename is specified then "-" is implied. Filehandle references,\r
-or objects that support the regular IO operations (like C<E<lt>$fhE<gt>>\r
-or C<$fh-<Egt>getline>) are also accepted; the handles must already be \r
-opened.\r
-\r
-If a second argument is given then it should be the name of the desired\r
-output file. If the special output filename "-" or ">&STDOUT" is given\r
-then the STDOUT filehandle is used for output (and no open or close is\r
-performed). If the special output filename ">&STDERR" is given then the\r
-STDERR filehandle is used for output (and no open or close is\r
-performed). If no output filehandle is currently in use and no output\r
-filename is specified, then "-" is implied.\r
-Alternatively, filehandle references or objects that support the regular\r
-IO operations (like C<print>, e.g. L<IO::String>) are also accepted;\r
-the object must already be opened.\r
-\r
-This method does I<not> usually need to be overridden by subclasses.\r
-\r
-=cut\r
-\r
-sub parse_from_file {\r
-    my $self = shift;\r
-    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();\r
-    my ($infile, $outfile) = @_;\r
-    my ($in_fh,  $out_fh);\r
-    if ($] < 5.006) {\r
-      ($in_fh,  $out_fh) = (gensym(), gensym());\r
-    }\r
-    my ($close_input, $close_output) = (0, 0);\r
-    local *myData = $self;\r
-    local *_;\r
-\r
-    ## Is $infile a filename or a (possibly implied) filehandle\r
-    if (defined $infile && ref $infile) {\r
-        if (ref($infile) =~ /^(SCALAR|ARRAY|HASH|CODE|REF)$/) {\r
-            croak "Input from $1 reference not supported!\n";\r
-        }\r
-        ## Must be a filehandle-ref (or else assume its a ref to an object\r
-        ## that supports the common IO read operations).\r
-        $myData{_INFILE} = ${$infile};\r
-        $in_fh = $infile;\r
-    }\r
-    elsif (!defined($infile) || !length($infile) || ($infile eq '-')\r
-        || ($infile =~ /^<&(?:STDIN|0)$/i))\r
-    {\r
-        ## Not a filename, just a string implying STDIN\r
-        $infile ||= '-';\r
-        $myData{_INFILE} = '<standard input>';\r
-        $in_fh = \*STDIN;\r
-    }\r
-    else {\r
-        ## We have a filename, open it for reading\r
-        $myData{_INFILE} = $infile;\r
-        open($in_fh, "< $infile")  or\r
-             croak "Can't open $infile for reading: $!\n";\r
-        $close_input = 1;\r
-    }\r
-\r
-    ## NOTE: we need to be *very* careful when "defaulting" the output\r
-    ## file. We only want to use a default if this is the beginning of\r
-    ## the entire document (but *not* if this is an included file). We\r
-    ## determine this by seeing if the input stream stack has been set-up\r
-    ## already\r
-\r
-    ## Is $outfile a filename, a (possibly implied) filehandle, maybe a ref?\r
-    if (ref $outfile) {\r
-        ## we need to check for ref() first, as other checks involve reading\r
-        if (ref($outfile) =~ /^(ARRAY|HASH|CODE)$/) {\r
-            croak "Output to $1 reference not supported!\n";\r
-        }\r
-        elsif (ref($outfile) eq 'SCALAR') {\r
-#           # NOTE: IO::String isn't a part of the perl distribution,\r
-#           #       so probably we shouldn't support this case...\r
-#           require IO::String;\r
-#           $myData{_OUTFILE} = "$outfile";\r
-#           $out_fh = IO::String->new($outfile);\r
-            croak "Output to SCALAR reference not supported!\n";\r
-        }\r
-        else {\r
-            ## Must be a filehandle-ref (or else assume its a ref to an\r
-            ## object that supports the common IO write operations).\r
-            $myData{_OUTFILE} = ${$outfile};\r
-            $out_fh = $outfile;\r
-        }\r
-    }\r
-    elsif (!defined($outfile) || !length($outfile) || ($outfile eq '-')\r
-        || ($outfile =~ /^>&?(?:STDOUT|1)$/i))\r
-    {\r
-        if (defined $myData{_TOP_STREAM}) {\r
-            $out_fh = $myData{_OUTPUT};\r
-        }\r
-        else {\r
-            ## Not a filename, just a string implying STDOUT\r
-            $outfile ||= '-';\r
-            $myData{_OUTFILE} = '<standard output>';\r
-            $out_fh  = \*STDOUT;\r
-        }\r
-    }\r
-    elsif ($outfile =~ /^>&(STDERR|2)$/i) {\r
-        ## Not a filename, just a string implying STDERR\r
-        $myData{_OUTFILE} = '<standard error>';\r
-        $out_fh  = \*STDERR;\r
-    }\r
-    else {\r
-        ## We have a filename, open it for writing\r
-        $myData{_OUTFILE} = $outfile;\r
-        (-d $outfile) and croak "$outfile is a directory, not POD input!\n";\r
-        open($out_fh, "> $outfile")  or\r
-             croak "Can't open $outfile for writing: $!\n";\r
-        $close_output = 1;\r
-    }\r
-\r
-    ## Whew! That was a lot of work to set up reasonably/robust behavior\r
-    ## in the case of a non-filename for reading and writing. Now we just\r
-    ## have to parse the input and close the handles when we're finished.\r
-    $self->parse_from_filehandle(\%opts, $in_fh, $out_fh);\r
-\r
-    $close_input  and\r
-        close($in_fh) || croak "Can't close $infile after reading: $!\n";\r
-    $close_output  and\r
-        close($out_fh) || croak "Can't close $outfile after writing: $!\n";\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 ACCESSOR METHODS\r
-\r
-Clients of B<Pod::Parser> should use the following methods to access\r
-instance data fields:\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<errorsub()>\r
-\r
-            $parser->errorsub("method_name");\r
-            $parser->errorsub(\&warn_user);\r
-            $parser->errorsub(sub { print STDERR, @_ });\r
-\r
-Specifies the method or subroutine to use when printing error messages\r
-about POD syntax. The supplied method/subroutine I<must> return TRUE upon\r
-successful printing of the message. If C<undef> is given, then the B<carp>\r
-builtin is used to issue error messages (this is the default behavior).\r
-\r
-            my $errorsub = $parser->errorsub()\r
-            my $errmsg = "This is an error message!\n"\r
-            (ref $errorsub) and &{$errorsub}($errmsg)\r
-                or (defined $errorsub) and $parser->$errorsub($errmsg)\r
-                    or  carp($errmsg);\r
-\r
-Returns a method name, or else a reference to the user-supplied subroutine\r
-used to print error messages. Returns C<undef> if the B<carp> builtin\r
-is used to issue error messages (this is the default behavior).\r
-\r
-=cut\r
-\r
-sub errorsub {\r
-   return (@_ > 1) ? ($_[0]->{_ERRORSUB} = $_[1]) : $_[0]->{_ERRORSUB};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<cutting()>\r
-\r
-            $boolean = $parser->cutting();\r
-\r
-Returns the current C<cutting> state: a boolean-valued scalar which\r
-evaluates to true if text from the input file is currently being "cut"\r
-(meaning it is I<not> considered part of the POD document).\r
-\r
-            $parser->cutting($boolean);\r
-\r
-Sets the current C<cutting> state to the given value and returns the\r
-result.\r
-\r
-=cut\r
-\r
-sub cutting {\r
-   return (@_ > 1) ? ($_[0]->{_CUTTING} = $_[1]) : $_[0]->{_CUTTING};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<parseopts()>\r
-\r
-When invoked with no additional arguments, B<parseopts> returns a hashtable\r
-of all the current parsing options.\r
-\r
-            ## See if we are parsing non-POD sections as well as POD ones\r
-            my %opts = $parser->parseopts();\r
-            $opts{'-want_nonPODs}' and print "-want_nonPODs\n";\r
-\r
-When invoked using a single string, B<parseopts> treats the string as the\r
-name of a parse-option and returns its corresponding value if it exists\r
-(returns C<undef> if it doesn't).\r
-\r
-            ## Did we ask to see '=cut' paragraphs?\r
-            my $want_cut = $parser->parseopts('-process_cut_cmd');\r
-            $want_cut and print "-process_cut_cmd\n";\r
-\r
-When invoked with multiple arguments, B<parseopts> treats them as\r
-key/value pairs and the specified parse-option names are set to the\r
-given values. Any unspecified parse-options are unaffected.\r
-\r
-            ## Set them back to the default\r
-            $parser->parseopts(-warnings => 0);\r
-\r
-When passed a single hash-ref, B<parseopts> uses that hash to completely\r
-reset the existing parse-options, all previous parse-option values\r
-are lost.\r
-\r
-            ## Reset all options to default \r
-            $parser->parseopts( { } );\r
-\r
-See L<"PARSING OPTIONS"> for more information on the name and meaning of each\r
-parse-option currently recognized.\r
-\r
-=cut\r
-\r
-sub parseopts {\r
-   local *myData = shift;\r
-   local *myOpts = ($myData{_PARSEOPTS} ||= {});\r
-   return %myOpts  if (@_ == 0);\r
-   if (@_ == 1) {\r
-      local $_ = shift;\r
-      return  ref($_)  ?  $myData{_PARSEOPTS} = $_  :  $myOpts{$_};\r
-   }\r
-   my @newOpts = (%myOpts, @_);\r
-   $myData{_PARSEOPTS} = { @newOpts };\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<output_file()>\r
-\r
-            $fname = $parser->output_file();\r
-\r
-Returns the name of the output file being written.\r
-\r
-=cut\r
-\r
-sub output_file {\r
-   return $_[0]->{_OUTFILE};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<output_handle()>\r
-\r
-            $fhandle = $parser->output_handle();\r
-\r
-Returns the output filehandle object.\r
-\r
-=cut\r
-\r
-sub output_handle {\r
-   return $_[0]->{_OUTPUT};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<input_file()>\r
-\r
-            $fname = $parser->input_file();\r
-\r
-Returns the name of the input file being read.\r
-\r
-=cut\r
-\r
-sub input_file {\r
-   return $_[0]->{_INFILE};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=head1 B<input_handle()>\r
-\r
-            $fhandle = $parser->input_handle();\r
-\r
-Returns the current input filehandle object.\r
-\r
-=cut\r
-\r
-sub input_handle {\r
-   return $_[0]->{_INPUT};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head1 B<input_streams()>\r
-\r
-            $listref = $parser->input_streams();\r
-\r
-Returns a reference to an array which corresponds to the stack of all\r
-the input streams that are currently in the middle of being parsed.\r
-\r
-While parsing an input stream, it is possible to invoke\r
-B<parse_from_file()> or B<parse_from_filehandle()> to parse a new input\r
-stream and then return to parsing the previous input stream. Each input\r
-stream to be parsed is pushed onto the end of this input stack\r
-before any of its input is read. The input stream that is currently\r
-being parsed is always at the end (or top) of the input stack. When an\r
-input stream has been exhausted, it is popped off the end of the\r
-input stack.\r
-\r
-Each element on this input stack is a reference to C<Pod::InputSource>\r
-object. Please see L<Pod::InputObjects> for more details.\r
-\r
-This method might be invoked when printing diagnostic messages, for example,\r
-to obtain the name and line number of the all input files that are currently\r
-being processed.\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub input_streams {\r
-   return $_[0]->{_INPUT_STREAMS};\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin __PRIVATE__\r
-\r
-=head1 B<top_stream()>\r
-\r
-            $hashref = $parser->top_stream();\r
-\r
-Returns a reference to the hash-table that represents the element\r
-that is currently at the top (end) of the input stream stack\r
-(see L<"input_streams()">). The return value will be the C<undef>\r
-if the input stack is empty.\r
-\r
-This method might be used when printing diagnostic messages, for example,\r
-to obtain the name and line number of the current input file.\r
-\r
-=end __PRIVATE__\r
-\r
-=cut\r
-\r
-sub top_stream {\r
-   return $_[0]->{_TOP_STREAM} || undef;\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 PRIVATE METHODS AND DATA\r
-\r
-B<Pod::Parser> makes use of several internal methods and data fields\r
-which clients should not need to see or use. For the sake of avoiding\r
-name collisions for client data and methods, these methods and fields\r
-are briefly discussed here. Determined hackers may obtain further\r
-information about them by reading the B<Pod::Parser> source code.\r
-\r
-Private data fields are stored in the hash-object whose reference is\r
-returned by the B<new()> constructor for this class. The names of all\r
-private methods and data-fields used by B<Pod::Parser> begin with a\r
-prefix of "_" and match the regular expression C</^_\w+$/>.\r
-\r
-=cut\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin _PRIVATE_\r
-\r
-=head1 B<_push_input_stream()>\r
-\r
-            $hashref = $parser->_push_input_stream($in_fh,$out_fh);\r
-\r
-This method will push the given input stream on the input stack and\r
-perform any necessary beginning-of-document or beginning-of-file\r
-processing. The argument C<$in_fh> is the input stream filehandle to\r
-push, and C<$out_fh> is the corresponding output filehandle to use (if\r
-it is not given or is undefined, then the current output stream is used,\r
-which defaults to standard output if it doesnt exist yet).\r
-\r
-The value returned will be reference to the hash-table that represents\r
-the new top of the input stream stack. I<Please Note> that it is\r
-possible for this method to use default values for the input and output\r
-file handles. If this happens, you will need to look at the C<INPUT>\r
-and C<OUTPUT> instance data members to determine their new values.\r
-\r
-=end _PRIVATE_\r
-\r
-=cut\r
-\r
-sub _push_input_stream {\r
-    my ($self, $in_fh, $out_fh) = @_;\r
-    local *myData = $self;\r
-\r
-    ## Initialize stuff for the entire document if this is *not*\r
-    ## an included file.\r
-    ##\r
-    ## NOTE: we need to be *very* careful when "defaulting" the output\r
-    ## filehandle. We only want to use a default value if this is the\r
-    ## beginning of the entire document (but *not* if this is an included\r
-    ## file).\r
-    unless (defined  $myData{_TOP_STREAM}) {\r
-        $out_fh  = \*STDOUT  unless (defined $out_fh);\r
-        $myData{_CUTTING}       = 1;   ## current "cutting" state\r
-        $myData{_INPUT_STREAMS} = [];  ## stack of all input streams\r
-    }\r
-\r
-    ## Initialize input indicators\r
-    $myData{_OUTFILE} = '(unknown)'  unless (defined  $myData{_OUTFILE});\r
-    $myData{_OUTPUT}  = $out_fh      if (defined  $out_fh);\r
-    $in_fh            = \*STDIN      unless (defined  $in_fh);\r
-    $myData{_INFILE}  = '(unknown)'  unless (defined  $myData{_INFILE});\r
-    $myData{_INPUT}   = $in_fh;\r
-    my $input_top     = $myData{_TOP_STREAM}\r
-                      = new Pod::InputSource(\r
-                            -name        => $myData{_INFILE},\r
-                            -handle      => $in_fh,\r
-                            -was_cutting => $myData{_CUTTING}\r
-                        );\r
-    local *input_stack = $myData{_INPUT_STREAMS};\r
-    push(@input_stack, $input_top);\r
-\r
-    ## Perform beginning-of-document and/or beginning-of-input processing\r
-    $self->begin_pod()  if (@input_stack == 1);\r
-    $self->begin_input();\r
-\r
-    return  $input_top;\r
-}\r
-\r
-##---------------------------------------------------------------------------\r
-\r
-=begin _PRIVATE_\r
-\r
-=head1 B<_pop_input_stream()>\r
-\r
-            $hashref = $parser->_pop_input_stream();\r
-\r
-This takes no arguments. It will perform any necessary end-of-file or\r
-end-of-document processing and then pop the current input stream from\r
-the top of the input stack.\r
-\r
-The value returned will be reference to the hash-table that represents\r
-the new top of the input stream stack.\r
-\r
-=end _PRIVATE_\r
-\r
-=cut\r
-\r
-sub _pop_input_stream {\r
-    my ($self) = @_;\r
-    local *myData = $self;\r
-    local *input_stack = $myData{_INPUT_STREAMS};\r
-\r
-    ## Perform end-of-input and/or end-of-document processing\r
-    $self->end_input()  if (@input_stack > 0);\r
-    $self->end_pod()    if (@input_stack == 1);\r
-\r
-    ## Restore cutting state to whatever it was before we started\r
-    ## parsing this file.\r
-    my $old_top = pop(@input_stack);\r
-    $myData{_CUTTING} = $old_top->was_cutting();\r
-\r
-    ## Don't forget to reset the input indicators\r
-    my $input_top = undef;\r
-    if (@input_stack > 0) {\r
-       $input_top = $myData{_TOP_STREAM} = $input_stack[-1];\r
-       $myData{_INFILE}  = $input_top->name();\r
-       $myData{_INPUT}   = $input_top->handle();\r
-    } else {\r
-       delete $myData{_TOP_STREAM};\r
-       delete $myData{_INPUT_STREAMS};\r
-    }\r
-\r
-    return  $input_top;\r
-}\r
-\r
-#############################################################################\r
-\r
-=head1 TREE-BASED PARSING\r
-\r
-If straightforward stream-based parsing wont meet your needs (as is\r
-likely the case for tasks such as translating PODs into structured\r
-markup languages like HTML and XML) then you may need to take the\r
-tree-based approach. Rather than doing everything in one pass and\r
-calling the B<interpolate()> method to expand sequences into text, it\r
-may be desirable to instead create a parse-tree using the B<parse_text()>\r
-method to return a tree-like structure which may contain an ordered\r
-list of children (each of which may be a text-string, or a similar\r
-tree-like structure).\r
-\r
-Pay special attention to L<"METHODS FOR PARSING AND PROCESSING"> and\r
-to the objects described in L<Pod::InputObjects>. The former describes\r
-the gory details and parameters for how to customize and extend the\r
-parsing behavior of B<Pod::Parser>. B<Pod::InputObjects> provides\r
-several objects that may all be used interchangeably as parse-trees. The\r
-most obvious one is the B<Pod::ParseTree> object. It defines the basic\r
-interface and functionality that all things trying to be a POD parse-tree\r
-should do. A B<Pod::ParseTree> is defined such that each "node" may be a\r
-text-string, or a reference to another parse-tree.  Each B<Pod::Paragraph>\r
-object and each B<Pod::InteriorSequence> object also supports the basic\r
-parse-tree interface.\r
-\r
-The B<parse_text()> method takes a given paragraph of text, and\r
-returns a parse-tree that contains one or more children, each of which\r
-may be a text-string, or an InteriorSequence object. There are also\r
-callback-options that may be passed to B<parse_text()> to customize\r
-the way it expands or transforms interior-sequences, as well as the\r
-returned result. These callbacks can be used to create a parse-tree\r
-with custom-made objects (which may or may not support the parse-tree\r
-interface, depending on how you choose to do it).\r
-\r
-If you wish to turn an entire POD document into a parse-tree, that process\r
-is fairly straightforward. The B<parse_text()> method is the key to doing\r
-this successfully. Every paragraph-callback (i.e. the polymorphic methods\r
-for B<command()>, B<verbatim()>, and B<textblock()> paragraphs) takes\r
-a B<Pod::Paragraph> object as an argument. Each paragraph object has a\r
-B<parse_tree()> method that can be used to get or set a corresponding\r
-parse-tree. So for each of those paragraph-callback methods, simply call\r
-B<parse_text()> with the options you desire, and then use the returned\r
-parse-tree to assign to the given paragraph object.\r
-\r
-That gives you a parse-tree for each paragraph - so now all you need is\r
-an ordered list of paragraphs. You can maintain that yourself as a data\r
-element in the object/hash. The most straightforward way would be simply\r
-to use an array-ref, with the desired set of custom "options" for each\r
-invocation of B<parse_text>. Let's assume the desired option-set is\r
-given by the hash C<%options>. Then we might do something like the\r
-following:\r
-\r
-    package MyPodParserTree;\r
-\r
-    @ISA = qw( Pod::Parser );\r
-\r
-    ...\r
-\r
-    sub begin_pod {\r
-        my $self = shift;\r
-        $self->{'-paragraphs'} = [];  ## initialize paragraph list\r
-    }\r
-\r
-    sub command { \r
-        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;\r
-        my $ptree = $parser->parse_text({%options}, $paragraph, ...);\r
-        $pod_para->parse_tree( $ptree );\r
-        push @{ $self->{'-paragraphs'} }, $pod_para;\r
-    }\r
-\r
-    sub verbatim { \r
-        my ($parser, $paragraph, $line_num, $pod_para) = @_;\r
-        push @{ $self->{'-paragraphs'} }, $pod_para;\r
-    }\r
-\r
-    sub textblock { \r
-        my ($parser, $paragraph, $line_num, $pod_para) = @_;\r
-        my $ptree = $parser->parse_text({%options}, $paragraph, ...);\r
-        $pod_para->parse_tree( $ptree );\r
-        push @{ $self->{'-paragraphs'} }, $pod_para;\r
-    }\r
-\r
-    ...\r
-\r
-    package main;\r
-    ...\r
-    my $parser = new MyPodParserTree(...);\r
-    $parser->parse_from_file(...);\r
-    my $paragraphs_ref = $parser->{'-paragraphs'};\r
-\r
-Of course, in this module-author's humble opinion, I'd be more inclined to\r
-use the existing B<Pod::ParseTree> object than a simple array. That way\r
-everything in it, paragraphs and sequences, all respond to the same core\r
-interface for all parse-tree nodes. The result would look something like:\r
-\r
-    package MyPodParserTree2;\r
-\r
-    ...\r
-\r
-    sub begin_pod {\r
-        my $self = shift;\r
-        $self->{'-ptree'} = new Pod::ParseTree;  ## initialize parse-tree\r
-    }\r
-\r
-    sub parse_tree {\r
-        ## convenience method to get/set the parse-tree for the entire POD\r
-        (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];\r
-        return $_[0]->{'-ptree'};\r
-    }\r
-\r
-    sub command { \r
-        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;\r
-        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);\r
-        $pod_para->parse_tree( $ptree );\r
-        $parser->parse_tree()->append( $pod_para );\r
-    }\r
-\r
-    sub verbatim { \r
-        my ($parser, $paragraph, $line_num, $pod_para) = @_;\r
-        $parser->parse_tree()->append( $pod_para );\r
-    }\r
-\r
-    sub textblock { \r
-        my ($parser, $paragraph, $line_num, $pod_para) = @_;\r
-        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);\r
-        $pod_para->parse_tree( $ptree );\r
-        $parser->parse_tree()->append( $pod_para );\r
-    }\r
-\r
-    ...\r
-\r
-    package main;\r
-    ...\r
-    my $parser = new MyPodParserTree2(...);\r
-    $parser->parse_from_file(...);\r
-    my $ptree = $parser->parse_tree;\r
-    ...\r
-\r
-Now you have the entire POD document as one great big parse-tree. You\r
-can even use the B<-expand_seq> option to B<parse_text> to insert\r
-whole different kinds of objects. Just don't expect B<Pod::Parser>\r
-to know what to do with them after that. That will need to be in your\r
-code. Or, alternatively, you can insert any object you like so long as\r
-it conforms to the B<Pod::ParseTree> interface.\r
-\r
-One could use this to create subclasses of B<Pod::Paragraphs> and\r
-B<Pod::InteriorSequences> for specific commands (or to create your own\r
-custom node-types in the parse-tree) and add some kind of B<emit()>\r
-method to each custom node/subclass object in the tree. Then all you'd\r
-need to do is recursively walk the tree in the desired order, processing\r
-the children (most likely from left to right) by formatting them if\r
-they are text-strings, or by calling their B<emit()> method if they\r
-are objects/references.\r
-\r
-=head1 CAVEATS\r
-\r
-Please note that POD has the notion of "paragraphs": this is something\r
-starting I<after> a blank (read: empty) line, with the single exception\r
-of the file start, which is also starting a paragraph. That means that\r
-especially a command (e.g. C<=head1>) I<must> be preceded with a blank\r
-line; C<__END__> is I<not> a blank line.\r
-\r
-=head1 SEE ALSO\r
-\r
-L<Pod::InputObjects>, L<Pod::Select>\r
-\r
-B<Pod::InputObjects> defines POD input objects corresponding to\r
-command paragraphs, parse-trees, and interior-sequences.\r
-\r
-B<Pod::Select> is a subclass of B<Pod::Parser> which provides the ability\r
-to selectively include and/or exclude sections of a POD document from being\r
-translated based upon the current heading, subheading, subsubheading, etc.\r
-\r
-=for __PRIVATE__\r
-B<Pod::Callbacks> is a subclass of B<Pod::Parser> which gives its users\r
-the ability the employ I<callback functions> instead of, or in addition\r
-to, overriding methods of the base class.\r
-\r
-=for __PRIVATE__\r
-B<Pod::Select> and B<Pod::Callbacks> do not override any\r
-methods nor do they define any new methods with the same name. Because\r
-of this, they may I<both> be used (in combination) as a base class of\r
-the same subclass in order to combine their functionality without\r
-causing any namespace clashes due to multiple inheritance.\r
-\r
-=head1 AUTHOR\r
-\r
-Please report bugs using L<http://rt.cpan.org>.\r
-\r
-Brad Appleton E<lt>bradapp@enteract.comE<gt>\r
-\r
-Based on code for B<Pod::Text> written by\r
-Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>\r
-\r
-=head1 LICENSE\r
-\r
-Pod-Parser is free software; you can redistribute it and/or modify it\r
-under the terms of the Artistic License distributed with Perl version\r
-5.000 or (at your option) any later version. Please refer to the\r
-Artistic License that came with your Perl distribution for more\r
-details. If your version of Perl was not distributed under the\r
-terms of the Artistic License, than you may distribute PodParser\r
-under the same terms as Perl itself.\r
-\r
-=cut\r
-\r
-1;\r
-# vim: ts=4 sw=4 et\r
+#############################################################################
+# Pod/Parser.pm -- package which defines a base class for parsing POD docs.
+#
+# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.
+# This file is part of "PodParser". PodParser is free software;
+# you can redistribute it and/or modify it under the same terms
+# as Perl itself.
+#############################################################################
+
+package Pod::Parser;
+use strict;
+
+## These "variables" are used as local "glob aliases" for performance
+use vars qw($VERSION @ISA %myData %myOpts @input_stack);
+$VERSION = '1.62';  ## Current version of this package
+require  5.005;    ## requires this Perl version or later
+
+#############################################################################
+
+=head1 NAME
+
+Pod::Parser - base class for creating POD filters and translators
+
+=head1 SYNOPSIS
+
+    use Pod::Parser;
+
+    package MyParser;
+    @ISA = qw(Pod::Parser);
+
+    sub command { 
+        my ($parser, $command, $paragraph, $line_num) = @_;
+        ## Interpret the command and its text; sample actions might be:
+        if ($command eq 'head1') { ... }
+        elsif ($command eq 'head2') { ... }
+        ## ... other commands and their actions
+        my $out_fh = $parser->output_handle();
+        my $expansion = $parser->interpolate($paragraph, $line_num);
+        print $out_fh $expansion;
+    }
+
+    sub verbatim { 
+        my ($parser, $paragraph, $line_num) = @_;
+        ## Format verbatim paragraph; sample actions might be:
+        my $out_fh = $parser->output_handle();
+        print $out_fh $paragraph;
+    }
+
+    sub textblock { 
+        my ($parser, $paragraph, $line_num) = @_;
+        ## Translate/Format this block of text; sample actions might be:
+        my $out_fh = $parser->output_handle();
+        my $expansion = $parser->interpolate($paragraph, $line_num);
+        print $out_fh $expansion;
+    }
+
+    sub interior_sequence { 
+        my ($parser, $seq_command, $seq_argument) = @_;
+        ## Expand an interior sequence; sample actions might be:
+        return "*$seq_argument*"     if ($seq_command eq 'B');
+        return "`$seq_argument'"     if ($seq_command eq 'C');
+        return "_${seq_argument}_'"  if ($seq_command eq 'I');
+        ## ... other sequence commands and their resulting text
+    }
+
+    package main;
+
+    ## Create a parser object and have it parse file whose name was
+    ## given on the command-line (use STDIN if no files were given).
+    $parser = new MyParser();
+    $parser->parse_from_filehandle(\*STDIN)  if (@ARGV == 0);
+    for (@ARGV) { $parser->parse_from_file($_); }
+
+=head1 REQUIRES
+
+perl5.005, Pod::InputObjects, Exporter, Symbol, Carp
+
+=head1 EXPORTS
+
+Nothing.
+
+=head1 DESCRIPTION
+
+B<NOTE: This module is considered legacy; modern Perl releases (5.18 and
+higher) are going to remove Pod-Parser from core and use L<Pod-Simple>
+for all things POD.>
+
+B<Pod::Parser> is a base class for creating POD filters and translators.
+It handles most of the effort involved with parsing the POD sections
+from an input stream, leaving subclasses free to be concerned only with
+performing the actual translation of text.
+
+B<Pod::Parser> parses PODs, and makes method calls to handle the various
+components of the POD. Subclasses of B<Pod::Parser> override these methods
+to translate the POD into whatever output format they desire.
+
+=head1 QUICK OVERVIEW
+
+To create a POD filter for translating POD documentation into some other
+format, you create a subclass of B<Pod::Parser> which typically overrides
+just the base class implementation for the following methods:
+
+=over 2
+
+=item *
+
+B<command()>
+
+=item *
+
+B<verbatim()>
+
+=item *
+
+B<textblock()>
+
+=item *
+
+B<interior_sequence()>
+
+=back
+
+You may also want to override the B<begin_input()> and B<end_input()>
+methods for your subclass (to perform any needed per-file and/or
+per-document initialization or cleanup).
+
+If you need to perform any preprocessing of input before it is parsed
+you may want to override one or more of B<preprocess_line()> and/or
+B<preprocess_paragraph()>.
+
+Sometimes it may be necessary to make more than one pass over the input
+files. If this is the case you have several options. You can make the
+first pass using B<Pod::Parser> and override your methods to store the
+intermediate results in memory somewhere for the B<end_pod()> method to
+process. You could use B<Pod::Parser> for several passes with an
+appropriate state variable to control the operation for each pass. If
+your input source can't be reset to start at the beginning, you can
+store it in some other structure as a string or an array and have that
+structure implement a B<getline()> method (which is all that
+B<parse_from_filehandle()> uses to read input).
+
+Feel free to add any member data fields you need to keep track of things
+like current font, indentation, horizontal or vertical position, or
+whatever else you like. Be sure to read L<"PRIVATE METHODS AND DATA">
+to avoid name collisions.
+
+For the most part, the B<Pod::Parser> base class should be able to
+do most of the input parsing for you and leave you free to worry about
+how to interpret the commands and translate the result.
+
+Note that all we have described here in this quick overview is the
+simplest most straightforward use of B<Pod::Parser> to do stream-based
+parsing. It is also possible to use the B<Pod::Parser::parse_text> function
+to do more sophisticated tree-based parsing. See L<"TREE-BASED PARSING">.
+
+=head1 PARSING OPTIONS
+
+A I<parse-option> is simply a named option of B<Pod::Parser> with a
+value that corresponds to a certain specified behavior. These various
+behaviors of B<Pod::Parser> may be enabled/disabled by setting
+or unsetting one or more I<parse-options> using the B<parseopts()> method.
+The set of currently accepted parse-options is as follows:
+
+=over 3
+
+=item B<-want_nonPODs> (default: unset)
+
+Normally (by default) B<Pod::Parser> will only provide access to
+the POD sections of the input. Input paragraphs that are not part
+of the POD-format documentation are not made available to the caller
+(not even using B<preprocess_paragraph()>). Setting this option to a
+non-empty, non-zero value will allow B<preprocess_paragraph()> to see
+non-POD sections of the input as well as POD sections. The B<cutting()>
+method can be used to determine if the corresponding paragraph is a POD
+paragraph, or some other input paragraph.
+
+=item B<-process_cut_cmd> (default: unset)
+
+Normally (by default) B<Pod::Parser> handles the C<=cut> POD directive
+by itself and does not pass it on to the caller for processing. Setting
+this option to a non-empty, non-zero value will cause B<Pod::Parser> to
+pass the C<=cut> directive to the caller just like any other POD command
+(and hence it may be processed by the B<command()> method).
+
+B<Pod::Parser> will still interpret the C<=cut> directive to mean that
+"cutting mode" has been (re)entered, but the caller will get a chance
+to capture the actual C<=cut> paragraph itself for whatever purpose
+it desires.
+
+=item B<-warnings> (default: unset)
+
+Normally (by default) B<Pod::Parser> recognizes a bare minimum of
+pod syntax errors and warnings and issues diagnostic messages
+for errors, but not for warnings. (Use B<Pod::Checker> to do more
+thorough checking of POD syntax.) Setting this option to a non-empty,
+non-zero value will cause B<Pod::Parser> to issue diagnostics for
+the few warnings it recognizes as well as the errors.
+
+=back
+
+Please see L<"parseopts()"> for a complete description of the interface
+for the setting and unsetting of parse-options.
+
+=cut
+
+#############################################################################
+
+#use diagnostics;
+use Pod::InputObjects;
+use Carp;
+use Exporter;
+BEGIN {
+   if ($] < 5.006) {
+      require Symbol;
+      import Symbol;
+   }
+}
+@ISA = qw(Exporter);
+
+#############################################################################
+
+=head1 RECOMMENDED SUBROUTINE/METHOD OVERRIDES
+
+B<Pod::Parser> provides several methods which most subclasses will probably
+want to override. These methods are as follows:
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head1 B<command()>
+
+            $parser->command($cmd,$text,$line_num,$pod_para);
+
+This method should be overridden by subclasses to take the appropriate
+action when a POD command paragraph (denoted by a line beginning with
+"=") is encountered. When such a POD directive is seen in the input,
+this method is called and is passed:
+
+=over 3
+
+=item C<$cmd>
+
+the name of the command for this POD paragraph
+
+=item C<$text>
+
+the paragraph text for the given POD paragraph command.
+
+=item C<$line_num>
+
+the line-number of the beginning of the paragraph
+
+=item C<$pod_para>
+
+a reference to a C<Pod::Paragraph> object which contains further
+information about the paragraph command (see L<Pod::InputObjects>
+for details).
+
+=back
+
+B<Note> that this method I<is> called for C<=pod> paragraphs.
+
+The base class implementation of this method simply treats the raw POD
+command as normal block of paragraph text (invoking the B<textblock()>
+method with the command paragraph).
+
+=cut
+
+sub command {
+    my ($self, $cmd, $text, $line_num, $pod_para)  = @_;
+    ## Just treat this like a textblock
+    $self->textblock($pod_para->raw_text(), $line_num, $pod_para);
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<verbatim()>
+
+            $parser->verbatim($text,$line_num,$pod_para);
+
+This method may be overridden by subclasses to take the appropriate
+action when a block of verbatim text is encountered. It is passed the
+following parameters:
+
+=over 3
+
+=item C<$text>
+
+the block of text for the verbatim paragraph
+
+=item C<$line_num>
+
+the line-number of the beginning of the paragraph
+
+=item C<$pod_para>
+
+a reference to a C<Pod::Paragraph> object which contains further
+information about the paragraph (see L<Pod::InputObjects>
+for details).
+
+=back
+
+The base class implementation of this method simply prints the textblock
+(unmodified) to the output filehandle.
+
+=cut
+
+sub verbatim {
+    my ($self, $text, $line_num, $pod_para) = @_;
+    my $out_fh = $self->{_OUTPUT};
+    print $out_fh $text;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<textblock()>
+
+            $parser->textblock($text,$line_num,$pod_para);
+
+This method may be overridden by subclasses to take the appropriate
+action when a normal block of POD text is encountered (although the base
+class method will usually do what you want). It is passed the following
+parameters:
+
+=over 3
+
+=item C<$text>
+
+the block of text for the a POD paragraph
+
+=item C<$line_num>
+
+the line-number of the beginning of the paragraph
+
+=item C<$pod_para>
+
+a reference to a C<Pod::Paragraph> object which contains further
+information about the paragraph (see L<Pod::InputObjects>
+for details).
+
+=back
+
+In order to process interior sequences, subclasses implementations of
+this method will probably want to invoke either B<interpolate()> or
+B<parse_text()>, passing it the text block C<$text>, and the corresponding
+line number in C<$line_num>, and then perform any desired processing upon
+the returned result.
+
+The base class implementation of this method simply prints the text block
+as it occurred in the input stream).
+
+=cut
+
+sub textblock {
+    my ($self, $text, $line_num, $pod_para) = @_;
+    my $out_fh = $self->{_OUTPUT};
+    print $out_fh $self->interpolate($text, $line_num);
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<interior_sequence()>
+
+            $parser->interior_sequence($seq_cmd,$seq_arg,$pod_seq);
+
+This method should be overridden by subclasses to take the appropriate
+action when an interior sequence is encountered. An interior sequence is
+an embedded command within a block of text which appears as a command
+name (usually a single uppercase character) followed immediately by a
+string of text which is enclosed in angle brackets. This method is
+passed the sequence command C<$seq_cmd> and the corresponding text
+C<$seq_arg>. It is invoked by the B<interpolate()> method for each interior
+sequence that occurs in the string that it is passed. It should return
+the desired text string to be used in place of the interior sequence.
+The C<$pod_seq> argument is a reference to a C<Pod::InteriorSequence>
+object which contains further information about the interior sequence.
+Please see L<Pod::InputObjects> for details if you need to access this
+additional information.
+
+Subclass implementations of this method may wish to invoke the 
+B<nested()> method of C<$pod_seq> to see if it is nested inside
+some other interior-sequence (and if so, which kind).
+
+The base class implementation of the B<interior_sequence()> method
+simply returns the raw text of the interior sequence (as it occurred
+in the input) to the caller.
+
+=cut
+
+sub interior_sequence {
+    my ($self, $seq_cmd, $seq_arg, $pod_seq) = @_;
+    ## Just return the raw text of the interior sequence
+    return  $pod_seq->raw_text();
+}
+
+#############################################################################
+
+=head1 OPTIONAL SUBROUTINE/METHOD OVERRIDES
+
+B<Pod::Parser> provides several methods which subclasses may want to override
+to perform any special pre/post-processing. These methods do I<not> have to
+be overridden, but it may be useful for subclasses to take advantage of them.
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head1 B<new()>
+
+            my $parser = Pod::Parser->new();
+
+This is the constructor for B<Pod::Parser> and its subclasses. You
+I<do not> need to override this method! It is capable of constructing
+subclass objects as well as base class objects, provided you use
+any of the following constructor invocation styles:
+
+    my $parser1 = MyParser->new();
+    my $parser2 = new MyParser();
+    my $parser3 = $parser2->new();
+
+where C<MyParser> is some subclass of B<Pod::Parser>.
+
+Using the syntax C<MyParser::new()> to invoke the constructor is I<not>
+recommended, but if you insist on being able to do this, then the
+subclass I<will> need to override the B<new()> constructor method. If
+you do override the constructor, you I<must> be sure to invoke the
+B<initialize()> method of the newly blessed object.
+
+Using any of the above invocations, the first argument to the
+constructor is always the corresponding package name (or object
+reference). No other arguments are required, but if desired, an
+associative array (or hash-table) my be passed to the B<new()>
+constructor, as in:
+
+    my $parser1 = MyParser->new( MYDATA => $value1, MOREDATA => $value2 );
+    my $parser2 = new MyParser( -myflag => 1 );
+
+All arguments passed to the B<new()> constructor will be treated as
+key/value pairs in a hash-table. The newly constructed object will be
+initialized by copying the contents of the given hash-table (which may
+have been empty). The B<new()> constructor for this class and all of its
+subclasses returns a blessed reference to the initialized object (hash-table).
+
+=cut
+
+sub new {
+    ## Determine if we were called via an object-ref or a classname
+    my ($this,%params) = @_;
+    my $class = ref($this) || $this;
+    ## Any remaining arguments are treated as initial values for the
+    ## hash that is used to represent this object.
+    my $self = { %params };
+    ## Bless ourselves into the desired class and perform any initialization
+    bless $self, $class;
+    $self->initialize();
+    return $self;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<initialize()>
+
+            $parser->initialize();
+
+This method performs any necessary object initialization. It takes no
+arguments (other than the object instance of course, which is typically
+copied to a local variable named C<$self>). If subclasses override this
+method then they I<must> be sure to invoke C<$self-E<gt>SUPER::initialize()>.
+
+=cut
+
+sub initialize {
+    #my $self = shift;
+    #return;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<begin_pod()>
+
+            $parser->begin_pod();
+
+This method is invoked at the beginning of processing for each POD
+document that is encountered in the input. Subclasses should override
+this method to perform any per-document initialization.
+
+=cut
+
+sub begin_pod {
+    #my $self = shift;
+    #return;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<begin_input()>
+
+            $parser->begin_input();
+
+This method is invoked by B<parse_from_filehandle()> immediately I<before>
+processing input from a filehandle. The base class implementation does
+nothing, however, subclasses may override it to perform any per-file
+initializations.
+
+Note that if multiple files are parsed for a single POD document
+(perhaps the result of some future C<=include> directive) this method
+is invoked for every file that is parsed. If you wish to perform certain
+initializations once per document, then you should use B<begin_pod()>.
+
+=cut
+
+sub begin_input {
+    #my $self = shift;
+    #return;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<end_input()>
+
+            $parser->end_input();
+
+This method is invoked by B<parse_from_filehandle()> immediately I<after>
+processing input from a filehandle. The base class implementation does
+nothing, however, subclasses may override it to perform any per-file
+cleanup actions.
+
+Please note that if multiple files are parsed for a single POD document
+(perhaps the result of some kind of C<=include> directive) this method
+is invoked for every file that is parsed. If you wish to perform certain
+cleanup actions once per document, then you should use B<end_pod()>.
+
+=cut
+
+sub end_input {
+    #my $self = shift;
+    #return;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<end_pod()>
+
+            $parser->end_pod();
+
+This method is invoked at the end of processing for each POD document
+that is encountered in the input. Subclasses should override this method
+to perform any per-document finalization.
+
+=cut
+
+sub end_pod {
+    #my $self = shift;
+    #return;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<preprocess_line()>
+
+          $textline = $parser->preprocess_line($text, $line_num);
+
+This method should be overridden by subclasses that wish to perform
+any kind of preprocessing for each I<line> of input (I<before> it has
+been determined whether or not it is part of a POD paragraph). The
+parameter C<$text> is the input line; and the parameter C<$line_num> is
+the line number of the corresponding text line.
+
+The value returned should correspond to the new text to use in its
+place.  If the empty string or an undefined value is returned then no
+further processing will be performed for this line.
+
+Please note that the B<preprocess_line()> method is invoked I<before>
+the B<preprocess_paragraph()> method. After all (possibly preprocessed)
+lines in a paragraph have been assembled together and it has been
+determined that the paragraph is part of the POD documentation from one
+of the selected sections, then B<preprocess_paragraph()> is invoked.
+
+The base class implementation of this method returns the given text.
+
+=cut
+
+sub preprocess_line {
+    my ($self, $text, $line_num) = @_;
+    return  $text;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<preprocess_paragraph()>
+
+            $textblock = $parser->preprocess_paragraph($text, $line_num);
+
+This method should be overridden by subclasses that wish to perform any
+kind of preprocessing for each block (paragraph) of POD documentation
+that appears in the input stream. The parameter C<$text> is the POD
+paragraph from the input file; and the parameter C<$line_num> is the
+line number for the beginning of the corresponding paragraph.
+
+The value returned should correspond to the new text to use in its
+place If the empty string is returned or an undefined value is
+returned, then the given C<$text> is ignored (not processed).
+
+This method is invoked after gathering up all the lines in a paragraph
+and after determining the cutting state of the paragraph,
+but before trying to further parse or interpret them. After
+B<preprocess_paragraph()> returns, the current cutting state (which
+is returned by C<$self-E<gt>cutting()>) is examined. If it evaluates
+to true then input text (including the given C<$text>) is cut (not
+processed) until the next POD directive is encountered.
+
+Please note that the B<preprocess_line()> method is invoked I<before>
+the B<preprocess_paragraph()> method. After all (possibly preprocessed)
+lines in a paragraph have been assembled together and either it has been
+determined that the paragraph is part of the POD documentation from one
+of the selected sections or the C<-want_nonPODs> option is true,
+then B<preprocess_paragraph()> is invoked.
+
+The base class implementation of this method returns the given text.
+
+=cut
+
+sub preprocess_paragraph {
+    my ($self, $text, $line_num) = @_;
+    return  $text;
+}
+
+#############################################################################
+
+=head1 METHODS FOR PARSING AND PROCESSING
+
+B<Pod::Parser> provides several methods to process input text. These
+methods typically won't need to be overridden (and in some cases they
+can't be overridden), but subclasses may want to invoke them to exploit
+their functionality.
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head1 B<parse_text()>
+
+            $ptree1 = $parser->parse_text($text, $line_num);
+            $ptree2 = $parser->parse_text({%opts}, $text, $line_num);
+            $ptree3 = $parser->parse_text(\%opts, $text, $line_num);
+
+This method is useful if you need to perform your own interpolation 
+of interior sequences and can't rely upon B<interpolate> to expand
+them in simple bottom-up order.
+
+The parameter C<$text> is a string or block of text to be parsed
+for interior sequences; and the parameter C<$line_num> is the
+line number corresponding to the beginning of C<$text>.
+
+B<parse_text()> will parse the given text into a parse-tree of "nodes."
+and interior-sequences.  Each "node" in the parse tree is either a
+text-string, or a B<Pod::InteriorSequence>.  The result returned is a
+parse-tree of type B<Pod::ParseTree>. Please see L<Pod::InputObjects>
+for more information about B<Pod::InteriorSequence> and B<Pod::ParseTree>.
+
+If desired, an optional hash-ref may be specified as the first argument
+to customize certain aspects of the parse-tree that is created and
+returned. The set of recognized option keywords are:
+
+=over 3
+
+=item B<-expand_seq> =E<gt> I<code-ref>|I<method-name>
+
+Normally, the parse-tree returned by B<parse_text()> will contain an
+unexpanded C<Pod::InteriorSequence> object for each interior-sequence
+encountered. Specifying B<-expand_seq> tells B<parse_text()> to "expand"
+every interior-sequence it sees by invoking the referenced function
+(or named method of the parser object) and using the return value as the
+expanded result.
+
+If a subroutine reference was given, it is invoked as:
+
+  &$code_ref( $parser, $sequence )
+
+and if a method-name was given, it is invoked as:
+
+  $parser->method_name( $sequence )
+
+where C<$parser> is a reference to the parser object, and C<$sequence>
+is a reference to the interior-sequence object.
+[I<NOTE>: If the B<interior_sequence()> method is specified, then it is
+invoked according to the interface specified in L<"interior_sequence()">].
+
+=item B<-expand_text> =E<gt> I<code-ref>|I<method-name>
+
+Normally, the parse-tree returned by B<parse_text()> will contain a
+text-string for each contiguous sequence of characters outside of an
+interior-sequence. Specifying B<-expand_text> tells B<parse_text()> to
+"preprocess" every such text-string it sees by invoking the referenced
+function (or named method of the parser object) and using the return value
+as the preprocessed (or "expanded") result. [Note that if the result is
+an interior-sequence, then it will I<not> be expanded as specified by the
+B<-expand_seq> option; Any such recursive expansion needs to be handled by
+the specified callback routine.]
+
+If a subroutine reference was given, it is invoked as:
+
+  &$code_ref( $parser, $text, $ptree_node )
+
+and if a method-name was given, it is invoked as:
+
+  $parser->method_name( $text, $ptree_node )
+
+where C<$parser> is a reference to the parser object, C<$text> is the
+text-string encountered, and C<$ptree_node> is a reference to the current
+node in the parse-tree (usually an interior-sequence object or else the
+top-level node of the parse-tree).
+
+=item B<-expand_ptree> =E<gt> I<code-ref>|I<method-name>
+
+Rather than returning a C<Pod::ParseTree>, pass the parse-tree as an
+argument to the referenced subroutine (or named method of the parser
+object) and return the result instead of the parse-tree object.
+
+If a subroutine reference was given, it is invoked as:
+
+  &$code_ref( $parser, $ptree )
+
+and if a method-name was given, it is invoked as:
+
+  $parser->method_name( $ptree )
+
+where C<$parser> is a reference to the parser object, and C<$ptree>
+is a reference to the parse-tree object.
+
+=back
+
+=cut
+
+sub parse_text {
+    my $self = shift;
+    local $_ = '';
+
+    ## Get options and set any defaults
+    my %opts = (ref $_[0]) ? %{ shift() } : ();
+    my $expand_seq   = $opts{'-expand_seq'}   || undef;
+    my $expand_text  = $opts{'-expand_text'}  || undef;
+    my $expand_ptree = $opts{'-expand_ptree'} || undef;
+
+    my $text = shift;
+    my $line = shift;
+    my $file = $self->input_file();
+    my $cmd  = "";
+
+    ## Convert method calls into closures, for our convenience
+    my $xseq_sub   = $expand_seq;
+    my $xtext_sub  = $expand_text;
+    my $xptree_sub = $expand_ptree;
+    if (defined $expand_seq  and  $expand_seq eq 'interior_sequence') {
+        ## If 'interior_sequence' is the method to use, we have to pass
+        ## more than just the sequence object, we also need to pass the
+        ## sequence name and text.
+        $xseq_sub = sub {
+            my ($sself, $iseq) = @_;
+            my $args = join('', $iseq->parse_tree->children);
+            return  $sself->interior_sequence($iseq->name, $args, $iseq);
+        };
+    }
+    ref $xseq_sub    or  $xseq_sub   = sub { shift()->$expand_seq(@_) };
+    ref $xtext_sub   or  $xtext_sub  = sub { shift()->$expand_text(@_) };
+    ref $xptree_sub  or  $xptree_sub = sub { shift()->$expand_ptree(@_) };
+
+    ## Keep track of the "current" interior sequence, and maintain a stack
+    ## of "in progress" sequences.
+    ##
+    ## NOTE that we push our own "accumulator" at the very beginning of the
+    ## stack. It's really a parse-tree, not a sequence; but it implements
+    ## the methods we need so we can use it to gather-up all the sequences
+    ## and strings we parse. Thus, by the end of our parsing, it should be
+    ## the only thing left on our stack and all we have to do is return it!
+    ##
+    my $seq       = Pod::ParseTree->new();
+    my @seq_stack = ($seq);
+    my ($ldelim, $rdelim) = ('', '');
+
+    ## Iterate over all sequence starts text (NOTE: split with
+    ## capturing parens keeps the delimiters)
+    $_ = $text;
+    my @tokens = split /([A-Z]<(?:<+(?:\r?\n|[ \t]))?)/;
+    while ( @tokens ) {
+        $_ = shift @tokens;
+        ## Look for the beginning of a sequence
+        if ( /^([A-Z])(<(?:<+(?:\r?\n|[ \t]))?)$/ ) {
+            ## Push a new sequence onto the stack of those "in-progress"
+            my $ldelim_orig;
+            ($cmd, $ldelim_orig) = ($1, $2);
+            ($ldelim = $ldelim_orig) =~ s/\s+$//;
+            ($rdelim = $ldelim) =~ tr/</>/;
+            $seq = Pod::InteriorSequence->new(
+                       -name   => $cmd,
+                       -ldelim => $ldelim_orig,  -rdelim => $rdelim,
+                       -file   => $file,    -line   => $line
+                   );
+            (@seq_stack > 1)  and  $seq->nested($seq_stack[-1]);
+            push @seq_stack, $seq;
+        }
+        ## Look for sequence ending
+        elsif ( @seq_stack > 1 ) {
+            ## Make sure we match the right kind of closing delimiter
+            my ($seq_end, $post_seq) = ('', '');
+            if ( ($ldelim eq '<'   and  /\A(.*?)(>)/s)
+                 or  /\A(.*?)(\s+$rdelim)/s )
+            {
+                ## Found end-of-sequence, capture the interior and the
+                ## closing the delimiter, and put the rest back on the
+                ## token-list
+                $post_seq = substr($_, length($1) + length($2));
+                ($_, $seq_end) = ($1, $2);
+                (length $post_seq)  and  unshift @tokens, $post_seq;
+            }
+            if (length) {
+                ## In the middle of a sequence, append this text to it, and
+                ## don't forget to "expand" it if that's what the caller wanted
+                $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);
+                $_ .= $seq_end;
+            }
+            if (length $seq_end) {
+                ## End of current sequence, record terminating delimiter
+                $seq->rdelim($seq_end);
+                ## Pop it off the stack of "in progress" sequences
+                pop @seq_stack;
+                ## Append result to its parent in current parse tree
+                $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq)
+                                                   : $seq);
+                ## Remember the current cmd-name and left-delimiter
+                if(@seq_stack > 1) {
+                    $cmd = $seq_stack[-1]->name;
+                    $ldelim = $seq_stack[-1]->ldelim;
+                    $rdelim = $seq_stack[-1]->rdelim;
+                } else {
+                    $cmd = $ldelim = $rdelim = '';
+                }
+            }
+        }
+        elsif (length) {
+            ## In the middle of a sequence, append this text to it, and
+            ## don't forget to "expand" it if that's what the caller wanted
+            $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_);
+        }
+        ## Keep track of line count
+        $line += /\n/;
+        ## Remember the "current" sequence
+        $seq = $seq_stack[-1];
+    }
+
+    ## Handle unterminated sequences
+    my $errorsub = (@seq_stack > 1) ? $self->errorsub() : undef;
+    while (@seq_stack > 1) {
+       ($cmd, $file, $line) = ($seq->name, $seq->file_line);
+       $ldelim  = $seq->ldelim;
+       ($rdelim = $ldelim) =~ tr/</>/;
+       $rdelim  =~ s/^(\S+)(\s*)$/$2$1/;
+       pop @seq_stack;
+       my $errmsg = "*** ERROR: unterminated ${cmd}${ldelim}...${rdelim}".
+                    " at line $line in file $file\n";
+       (ref $errorsub) and &{$errorsub}($errmsg)
+           or (defined $errorsub) and $self->$errorsub($errmsg)
+               or  carp($errmsg);
+       $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq) : $seq);
+       $seq = $seq_stack[-1];
+    }
+
+    ## Return the resulting parse-tree
+    my $ptree = (pop @seq_stack)->parse_tree;
+    return  $expand_ptree ? &$xptree_sub($self, $ptree) : $ptree;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<interpolate()>
+
+            $textblock = $parser->interpolate($text, $line_num);
+
+This method translates all text (including any embedded interior sequences)
+in the given text string C<$text> and returns the interpolated result. The
+parameter C<$line_num> is the line number corresponding to the beginning
+of C<$text>.
+
+B<interpolate()> merely invokes a private method to recursively expand
+nested interior sequences in bottom-up order (innermost sequences are
+expanded first). If there is a need to expand nested sequences in
+some alternate order, use B<parse_text> instead.
+
+=cut
+
+sub interpolate {
+    my($self, $text, $line_num) = @_;
+    my %parse_opts = ( -expand_seq => 'interior_sequence' );
+    my $ptree = $self->parse_text( \%parse_opts, $text, $line_num );
+    return  join '', $ptree->children();
+}
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head1 B<parse_paragraph()>
+
+            $parser->parse_paragraph($text, $line_num);
+
+This method takes the text of a POD paragraph to be processed, along
+with its corresponding line number, and invokes the appropriate method
+(one of B<command()>, B<verbatim()>, or B<textblock()>).
+
+For performance reasons, this method is invoked directly without any
+dynamic lookup; Hence subclasses may I<not> override it!
+
+=end __PRIVATE__
+
+=cut
+
+sub parse_paragraph {
+    my ($self, $text, $line_num) = @_;
+    local *myData = $self;  ## alias to avoid deref-ing overhead
+    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options
+    local $_;
+
+    ## See if we want to preprocess nonPOD paragraphs as well as POD ones.
+    my $wantNonPods = $myOpts{'-want_nonPODs'};
+
+    ## Update cutting status
+    $myData{_CUTTING} = 0 if $text =~ /^={1,2}\S/;
+
+    ## Perform any desired preprocessing if we wanted it this early
+    $wantNonPods  and  $text = $self->preprocess_paragraph($text, $line_num);
+
+    ## Ignore up until next POD directive if we are cutting
+    return if $myData{_CUTTING};
+
+    ## Now we know this is block of text in a POD section!
+
+    ##-----------------------------------------------------------------
+    ## This is a hook (hack ;-) for Pod::Select to do its thing without
+    ## having to override methods, but also without Pod::Parser assuming
+    ## $self is an instance of Pod::Select (if the _SELECTED_SECTIONS
+    ## field exists then we assume there is an is_selected() method for
+    ## us to invoke (calling $self->can('is_selected') could verify this
+    ## but that is more overhead than I want to incur)
+    ##-----------------------------------------------------------------
+
+    ## Ignore this block if it isn't in one of the selected sections
+    if (exists $myData{_SELECTED_SECTIONS}) {
+        $self->is_selected($text)  or  return ($myData{_CUTTING} = 1);
+    }
+
+    ## If we haven't already, perform any desired preprocessing and
+    ## then re-check the "cutting" state
+    unless ($wantNonPods) {
+       $text = $self->preprocess_paragraph($text, $line_num);
+       return 1  unless ((defined $text) and (length $text));
+       return 1  if ($myData{_CUTTING});
+    }
+
+    ## Look for one of the three types of paragraphs
+    my ($pfx, $cmd, $arg, $sep) = ('', '', '', '');
+    my $pod_para = undef;
+    if ($text =~ /^(={1,2})(?=\S)/) {
+        ## Looks like a command paragraph. Capture the command prefix used
+        ## ("=" or "=="), as well as the command-name, its paragraph text,
+        ## and whatever sequence of characters was used to separate them
+        $pfx = $1;
+        $_ = substr($text, length $pfx);
+        ($cmd, $sep, $text) = split /(\s+)/, $_, 2;
+        $sep = '' unless defined $sep;
+        $text = '' unless defined $text;
+        ## If this is a "cut" directive then we don't need to do anything
+        ## except return to "cutting" mode.
+        if ($cmd eq 'cut') {
+           $myData{_CUTTING} = 1;
+           return  unless $myOpts{'-process_cut_cmd'};
+        }
+    }
+    ## Save the attributes indicating how the command was specified.
+    $pod_para = new Pod::Paragraph(
+          -name      => $cmd,
+          -text      => $text,
+          -prefix    => $pfx,
+          -separator => $sep,
+          -file      => $myData{_INFILE},
+          -line      => $line_num
+    );
+    # ## Invoke appropriate callbacks
+    # if (exists $myData{_CALLBACKS}) {
+    #    ## Look through the callback list, invoke callbacks,
+    #    ## then see if we need to do the default actions
+    #    ## (invoke_callbacks will return true if we do).
+    #    return  1  unless $self->invoke_callbacks($cmd, $text, $line_num, $pod_para);
+    # }
+
+    # If the last paragraph ended in whitespace, and we're not between verbatim blocks, carp
+    if ($myData{_WHITESPACE} and $myOpts{'-warnings'}
+            and not ($text =~ /^\s+/ and ($myData{_PREVIOUS}||"") eq "verbatim")) {
+        my $errorsub = $self->errorsub();
+        my $line = $line_num - 1;
+        my $errmsg = "*** WARNING: line containing nothing but whitespace".
+                     " in paragraph at line $line in file $myData{_INFILE}\n";
+        (ref $errorsub) and &{$errorsub}($errmsg)
+            or (defined $errorsub) and $self->$errorsub($errmsg)
+                or  carp($errmsg);
+    }
+
+    if (length $cmd) {
+        ## A command paragraph
+        $self->command($cmd, $text, $line_num, $pod_para);
+        $myData{_PREVIOUS} = $cmd;
+    }
+    elsif ($text =~ /^\s+/) {
+        ## Indented text - must be a verbatim paragraph
+        $self->verbatim($text, $line_num, $pod_para);
+        $myData{_PREVIOUS} = "verbatim";
+    }
+    else {
+        ## Looks like an ordinary block of text
+        $self->textblock($text, $line_num, $pod_para);
+        $myData{_PREVIOUS} = "textblock";
+    }
+
+    # Update the whitespace for the next time around
+    #$myData{_WHITESPACE} = $text =~ /^[^\S\r\n]+\Z/m ? 1 : 0;
+    $myData{_WHITESPACE} = $text =~ /^[^\S\r\n]+\r*\Z/m ? 1 : 0;
+
+    return  1;
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<parse_from_filehandle()>
+
+            $parser->parse_from_filehandle($in_fh,$out_fh);
+
+This method takes an input filehandle (which is assumed to already be
+opened for reading) and reads the entire input stream looking for blocks
+(paragraphs) of POD documentation to be processed. If no first argument
+is given the default input filehandle C<STDIN> is used.
+
+The C<$in_fh> parameter may be any object that provides a B<getline()>
+method to retrieve a single line of input text (hence, an appropriate
+wrapper object could be used to parse PODs from a single string or an
+array of strings).
+
+Using C<$in_fh-E<gt>getline()>, input is read line-by-line and assembled
+into paragraphs or "blocks" (which are separated by lines containing
+nothing but whitespace). For each block of POD documentation
+encountered it will invoke a method to parse the given paragraph.
+
+If a second argument is given then it should correspond to a filehandle where
+output should be sent (otherwise the default output filehandle is
+C<STDOUT> if no output filehandle is currently in use).
+
+B<NOTE:> For performance reasons, this method caches the input stream at
+the top of the stack in a local variable. Any attempts by clients to
+change the stack contents during processing when in the midst executing
+of this method I<will not affect> the input stream used by the current
+invocation of this method.
+
+This method does I<not> usually need to be overridden by subclasses.
+
+=cut
+
+sub parse_from_filehandle {
+    my $self = shift;
+    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();
+    my ($in_fh, $out_fh) = @_;
+    $in_fh = \*STDIN  unless ($in_fh);
+    local *myData = $self;  ## alias to avoid deref-ing overhead
+    local *myOpts = ($myData{_PARSEOPTS} ||= {});  ## get parse-options
+    local $_;
+
+    ## Put this stream at the top of the stack and do beginning-of-input
+    ## processing. NOTE that $in_fh might be reset during this process.
+    my $topstream = $self->_push_input_stream($in_fh, $out_fh);
+    (exists $opts{-cutting})  and  $self->cutting( $opts{-cutting} );
+
+    ## Initialize line/paragraph
+    my ($textline, $paragraph) = ('', '');
+    my ($nlines, $plines) = (0, 0);
+
+    ## Use <$fh> instead of $fh->getline where possible (for speed)
+    $_ = ref $in_fh;
+    my $tied_fh = (/^(?:GLOB|FileHandle|IO::\w+)$/  or  tied $in_fh);
+
+    ## Read paragraphs line-by-line
+    while (defined ($textline = $tied_fh ? <$in_fh> : $in_fh->getline)) {
+        $textline = $self->preprocess_line($textline, ++$nlines);
+        next  unless ((defined $textline)  &&  (length $textline));
+
+        if ((! length $paragraph) && ($textline =~ /^==/)) {
+            ## '==' denotes a one-line command paragraph
+            $paragraph = $textline;
+            $plines    = 1;
+            $textline  = '';
+        } else {
+            ## Append this line to the current paragraph
+            $paragraph .= $textline;
+            ++$plines;
+        }
+
+        ## See if this line is blank and ends the current paragraph.
+        ## If it isn't, then keep iterating until it is.
+        next unless (($textline =~ /^[^\S\r\n]*[\r\n]*$/)
+                                     && (length $paragraph));
+
+        ## Now process the paragraph
+        parse_paragraph($self, $paragraph, ($nlines - $plines) + 1);
+        $paragraph = '';
+        $plines = 0;
+    }
+    ## Don't forget about the last paragraph in the file
+    if (length $paragraph) {
+       parse_paragraph($self, $paragraph, ($nlines - $plines) + 1)
+    }
+
+    ## Now pop the input stream off the top of the input stack.
+    $self->_pop_input_stream();
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<parse_from_file()>
+
+            $parser->parse_from_file($filename,$outfile);
+
+This method takes a filename and does the following:
+
+=over 2
+
+=item *
+
+opens the input and output files for reading
+(creating the appropriate filehandles)
+
+=item *
+
+invokes the B<parse_from_filehandle()> method passing it the
+corresponding input and output filehandles.
+
+=item *
+
+closes the input and output files.
+
+=back
+
+If the special input filename "", "-" or "<&STDIN" is given then the STDIN
+filehandle is used for input (and no open or close is performed). If no
+input filename is specified then "-" is implied. Filehandle references,
+or objects that support the regular IO operations (like C<E<lt>$fhE<gt>>
+or C<$fh-<Egt>getline>) are also accepted; the handles must already be 
+opened.
+
+If a second argument is given then it should be the name of the desired
+output file. If the special output filename "-" or ">&STDOUT" is given
+then the STDOUT filehandle is used for output (and no open or close is
+performed). If the special output filename ">&STDERR" is given then the
+STDERR filehandle is used for output (and no open or close is
+performed). If no output filehandle is currently in use and no output
+filename is specified, then "-" is implied.
+Alternatively, filehandle references or objects that support the regular
+IO operations (like C<print>, e.g. L<IO::String>) are also accepted;
+the object must already be opened.
+
+This method does I<not> usually need to be overridden by subclasses.
+
+=cut
+
+sub parse_from_file {
+    my $self = shift;
+    my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : ();
+    my ($infile, $outfile) = @_;
+    my ($in_fh,  $out_fh);
+    if ($] < 5.006) {
+      ($in_fh,  $out_fh) = (gensym(), gensym());
+    }
+    my ($close_input, $close_output) = (0, 0);
+    local *myData = $self;
+    local *_;
+
+    ## Is $infile a filename or a (possibly implied) filehandle
+    if (defined $infile && ref $infile) {
+        if (ref($infile) =~ /^(SCALAR|ARRAY|HASH|CODE|REF)$/) {
+            croak "Input from $1 reference not supported!\n";
+        }
+        ## Must be a filehandle-ref (or else assume its a ref to an object
+        ## that supports the common IO read operations).
+        $myData{_INFILE} = ${$infile};
+        $in_fh = $infile;
+    }
+    elsif (!defined($infile) || !length($infile) || ($infile eq '-')
+        || ($infile =~ /^<&(?:STDIN|0)$/i))
+    {
+        ## Not a filename, just a string implying STDIN
+        $infile ||= '-';
+        $myData{_INFILE} = '<standard input>';
+        $in_fh = \*STDIN;
+    }
+    else {
+        ## We have a filename, open it for reading
+        $myData{_INFILE} = $infile;
+        open($in_fh, "< $infile")  or
+             croak "Can't open $infile for reading: $!\n";
+        $close_input = 1;
+    }
+
+    ## NOTE: we need to be *very* careful when "defaulting" the output
+    ## file. We only want to use a default if this is the beginning of
+    ## the entire document (but *not* if this is an included file). We
+    ## determine this by seeing if the input stream stack has been set-up
+    ## already
+
+    ## Is $outfile a filename, a (possibly implied) filehandle, maybe a ref?
+    if (ref $outfile) {
+        ## we need to check for ref() first, as other checks involve reading
+        if (ref($outfile) =~ /^(ARRAY|HASH|CODE)$/) {
+            croak "Output to $1 reference not supported!\n";
+        }
+        elsif (ref($outfile) eq 'SCALAR') {
+#           # NOTE: IO::String isn't a part of the perl distribution,
+#           #       so probably we shouldn't support this case...
+#           require IO::String;
+#           $myData{_OUTFILE} = "$outfile";
+#           $out_fh = IO::String->new($outfile);
+            croak "Output to SCALAR reference not supported!\n";
+        }
+        else {
+            ## Must be a filehandle-ref (or else assume its a ref to an
+            ## object that supports the common IO write operations).
+            $myData{_OUTFILE} = ${$outfile};
+            $out_fh = $outfile;
+        }
+    }
+    elsif (!defined($outfile) || !length($outfile) || ($outfile eq '-')
+        || ($outfile =~ /^>&?(?:STDOUT|1)$/i))
+    {
+        if (defined $myData{_TOP_STREAM}) {
+            $out_fh = $myData{_OUTPUT};
+        }
+        else {
+            ## Not a filename, just a string implying STDOUT
+            $outfile ||= '-';
+            $myData{_OUTFILE} = '<standard output>';
+            $out_fh  = \*STDOUT;
+        }
+    }
+    elsif ($outfile =~ /^>&(STDERR|2)$/i) {
+        ## Not a filename, just a string implying STDERR
+        $myData{_OUTFILE} = '<standard error>';
+        $out_fh  = \*STDERR;
+    }
+    else {
+        ## We have a filename, open it for writing
+        $myData{_OUTFILE} = $outfile;
+        (-d $outfile) and croak "$outfile is a directory, not POD input!\n";
+        open($out_fh, "> $outfile")  or
+             croak "Can't open $outfile for writing: $!\n";
+        $close_output = 1;
+    }
+
+    ## Whew! That was a lot of work to set up reasonably/robust behavior
+    ## in the case of a non-filename for reading and writing. Now we just
+    ## have to parse the input and close the handles when we're finished.
+    $self->parse_from_filehandle(\%opts, $in_fh, $out_fh);
+
+    $close_input  and
+        close($in_fh) || croak "Can't close $infile after reading: $!\n";
+    $close_output  and
+        close($out_fh) || croak "Can't close $outfile after writing: $!\n";
+}
+
+#############################################################################
+
+=head1 ACCESSOR METHODS
+
+Clients of B<Pod::Parser> should use the following methods to access
+instance data fields:
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=head1 B<errorsub()>
+
+            $parser->errorsub("method_name");
+            $parser->errorsub(\&warn_user);
+            $parser->errorsub(sub { print STDERR, @_ });
+
+Specifies the method or subroutine to use when printing error messages
+about POD syntax. The supplied method/subroutine I<must> return TRUE upon
+successful printing of the message. If C<undef> is given, then the B<carp>
+builtin is used to issue error messages (this is the default behavior).
+
+            my $errorsub = $parser->errorsub()
+            my $errmsg = "This is an error message!\n"
+            (ref $errorsub) and &{$errorsub}($errmsg)
+                or (defined $errorsub) and $parser->$errorsub($errmsg)
+                    or  carp($errmsg);
+
+Returns a method name, or else a reference to the user-supplied subroutine
+used to print error messages. Returns C<undef> if the B<carp> builtin
+is used to issue error messages (this is the default behavior).
+
+=cut
+
+sub errorsub {
+   return (@_ > 1) ? ($_[0]->{_ERRORSUB} = $_[1]) : $_[0]->{_ERRORSUB};
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<cutting()>
+
+            $boolean = $parser->cutting();
+
+Returns the current C<cutting> state: a boolean-valued scalar which
+evaluates to true if text from the input file is currently being "cut"
+(meaning it is I<not> considered part of the POD document).
+
+            $parser->cutting($boolean);
+
+Sets the current C<cutting> state to the given value and returns the
+result.
+
+=cut
+
+sub cutting {
+   return (@_ > 1) ? ($_[0]->{_CUTTING} = $_[1]) : $_[0]->{_CUTTING};
+}
+
+##---------------------------------------------------------------------------
+
+##---------------------------------------------------------------------------
+
+=head1 B<parseopts()>
+
+When invoked with no additional arguments, B<parseopts> returns a hashtable
+of all the current parsing options.
+
+            ## See if we are parsing non-POD sections as well as POD ones
+            my %opts = $parser->parseopts();
+            $opts{'-want_nonPODs}' and print "-want_nonPODs\n";
+
+When invoked using a single string, B<parseopts> treats the string as the
+name of a parse-option and returns its corresponding value if it exists
+(returns C<undef> if it doesn't).
+
+            ## Did we ask to see '=cut' paragraphs?
+            my $want_cut = $parser->parseopts('-process_cut_cmd');
+            $want_cut and print "-process_cut_cmd\n";
+
+When invoked with multiple arguments, B<parseopts> treats them as
+key/value pairs and the specified parse-option names are set to the
+given values. Any unspecified parse-options are unaffected.
+
+            ## Set them back to the default
+            $parser->parseopts(-warnings => 0);
+
+When passed a single hash-ref, B<parseopts> uses that hash to completely
+reset the existing parse-options, all previous parse-option values
+are lost.
+
+            ## Reset all options to default 
+            $parser->parseopts( { } );
+
+See L<"PARSING OPTIONS"> for more information on the name and meaning of each
+parse-option currently recognized.
+
+=cut
+
+sub parseopts {
+   local *myData = shift;
+   local *myOpts = ($myData{_PARSEOPTS} ||= {});
+   return %myOpts  if (@_ == 0);
+   if (@_ == 1) {
+      local $_ = shift;
+      return  ref($_)  ?  $myData{_PARSEOPTS} = $_  :  $myOpts{$_};
+   }
+   my @newOpts = (%myOpts, @_);
+   $myData{_PARSEOPTS} = { @newOpts };
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<output_file()>
+
+            $fname = $parser->output_file();
+
+Returns the name of the output file being written.
+
+=cut
+
+sub output_file {
+   return $_[0]->{_OUTFILE};
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<output_handle()>
+
+            $fhandle = $parser->output_handle();
+
+Returns the output filehandle object.
+
+=cut
+
+sub output_handle {
+   return $_[0]->{_OUTPUT};
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<input_file()>
+
+            $fname = $parser->input_file();
+
+Returns the name of the input file being read.
+
+=cut
+
+sub input_file {
+   return $_[0]->{_INFILE};
+}
+
+##---------------------------------------------------------------------------
+
+=head1 B<input_handle()>
+
+            $fhandle = $parser->input_handle();
+
+Returns the current input filehandle object.
+
+=cut
+
+sub input_handle {
+   return $_[0]->{_INPUT};
+}
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head1 B<input_streams()>
+
+            $listref = $parser->input_streams();
+
+Returns a reference to an array which corresponds to the stack of all
+the input streams that are currently in the middle of being parsed.
+
+While parsing an input stream, it is possible to invoke
+B<parse_from_file()> or B<parse_from_filehandle()> to parse a new input
+stream and then return to parsing the previous input stream. Each input
+stream to be parsed is pushed onto the end of this input stack
+before any of its input is read. The input stream that is currently
+being parsed is always at the end (or top) of the input stack. When an
+input stream has been exhausted, it is popped off the end of the
+input stack.
+
+Each element on this input stack is a reference to C<Pod::InputSource>
+object. Please see L<Pod::InputObjects> for more details.
+
+This method might be invoked when printing diagnostic messages, for example,
+to obtain the name and line number of the all input files that are currently
+being processed.
+
+=end __PRIVATE__
+
+=cut
+
+sub input_streams {
+   return $_[0]->{_INPUT_STREAMS};
+}
+
+##---------------------------------------------------------------------------
+
+=begin __PRIVATE__
+
+=head1 B<top_stream()>
+
+            $hashref = $parser->top_stream();
+
+Returns a reference to the hash-table that represents the element
+that is currently at the top (end) of the input stream stack
+(see L<"input_streams()">). The return value will be the C<undef>
+if the input stack is empty.
+
+This method might be used when printing diagnostic messages, for example,
+to obtain the name and line number of the current input file.
+
+=end __PRIVATE__
+
+=cut
+
+sub top_stream {
+   return $_[0]->{_TOP_STREAM} || undef;
+}
+
+#############################################################################
+
+=head1 PRIVATE METHODS AND DATA
+
+B<Pod::Parser> makes use of several internal methods and data fields
+which clients should not need to see or use. For the sake of avoiding
+name collisions for client data and methods, these methods and fields
+are briefly discussed here. Determined hackers may obtain further
+information about them by reading the B<Pod::Parser> source code.
+
+Private data fields are stored in the hash-object whose reference is
+returned by the B<new()> constructor for this class. The names of all
+private methods and data-fields used by B<Pod::Parser> begin with a
+prefix of "_" and match the regular expression C</^_\w+$/>.
+
+=cut
+
+##---------------------------------------------------------------------------
+
+=begin _PRIVATE_
+
+=head1 B<_push_input_stream()>
+
+            $hashref = $parser->_push_input_stream($in_fh,$out_fh);
+
+This method will push the given input stream on the input stack and
+perform any necessary beginning-of-document or beginning-of-file
+processing. The argument C<$in_fh> is the input stream filehandle to
+push, and C<$out_fh> is the corresponding output filehandle to use (if
+it is not given or is undefined, then the current output stream is used,
+which defaults to standard output if it doesnt exist yet).
+
+The value returned will be reference to the hash-table that represents
+the new top of the input stream stack. I<Please Note> that it is
+possible for this method to use default values for the input and output
+file handles. If this happens, you will need to look at the C<INPUT>
+and C<OUTPUT> instance data members to determine their new values.
+
+=end _PRIVATE_
+
+=cut
+
+sub _push_input_stream {
+    my ($self, $in_fh, $out_fh) = @_;
+    local *myData = $self;
+
+    ## Initialize stuff for the entire document if this is *not*
+    ## an included file.
+    ##
+    ## NOTE: we need to be *very* careful when "defaulting" the output
+    ## filehandle. We only want to use a default value if this is the
+    ## beginning of the entire document (but *not* if this is an included
+    ## file).
+    unless (defined  $myData{_TOP_STREAM}) {
+        $out_fh  = \*STDOUT  unless (defined $out_fh);
+        $myData{_CUTTING}       = 1;   ## current "cutting" state
+        $myData{_INPUT_STREAMS} = [];  ## stack of all input streams
+    }
+
+    ## Initialize input indicators
+    $myData{_OUTFILE} = '(unknown)'  unless (defined  $myData{_OUTFILE});
+    $myData{_OUTPUT}  = $out_fh      if (defined  $out_fh);
+    $in_fh            = \*STDIN      unless (defined  $in_fh);
+    $myData{_INFILE}  = '(unknown)'  unless (defined  $myData{_INFILE});
+    $myData{_INPUT}   = $in_fh;
+    my $input_top     = $myData{_TOP_STREAM}
+                      = new Pod::InputSource(
+                            -name        => $myData{_INFILE},
+                            -handle      => $in_fh,
+                            -was_cutting => $myData{_CUTTING}
+                        );
+    local *input_stack = $myData{_INPUT_STREAMS};
+    push(@input_stack, $input_top);
+
+    ## Perform beginning-of-document and/or beginning-of-input processing
+    $self->begin_pod()  if (@input_stack == 1);
+    $self->begin_input();
+
+    return  $input_top;
+}
+
+##---------------------------------------------------------------------------
+
+=begin _PRIVATE_
+
+=head1 B<_pop_input_stream()>
+
+            $hashref = $parser->_pop_input_stream();
+
+This takes no arguments. It will perform any necessary end-of-file or
+end-of-document processing and then pop the current input stream from
+the top of the input stack.
+
+The value returned will be reference to the hash-table that represents
+the new top of the input stream stack.
+
+=end _PRIVATE_
+
+=cut
+
+sub _pop_input_stream {
+    my ($self) = @_;
+    local *myData = $self;
+    local *input_stack = $myData{_INPUT_STREAMS};
+
+    ## Perform end-of-input and/or end-of-document processing
+    $self->end_input()  if (@input_stack > 0);
+    $self->end_pod()    if (@input_stack == 1);
+
+    ## Restore cutting state to whatever it was before we started
+    ## parsing this file.
+    my $old_top = pop(@input_stack);
+    $myData{_CUTTING} = $old_top->was_cutting();
+
+    ## Don't forget to reset the input indicators
+    my $input_top = undef;
+    if (@input_stack > 0) {
+       $input_top = $myData{_TOP_STREAM} = $input_stack[-1];
+       $myData{_INFILE}  = $input_top->name();
+       $myData{_INPUT}   = $input_top->handle();
+    } else {
+       delete $myData{_TOP_STREAM};
+       delete $myData{_INPUT_STREAMS};
+    }
+
+    return  $input_top;
+}
+
+#############################################################################
+
+=head1 TREE-BASED PARSING
+
+If straightforward stream-based parsing wont meet your needs (as is
+likely the case for tasks such as translating PODs into structured
+markup languages like HTML and XML) then you may need to take the
+tree-based approach. Rather than doing everything in one pass and
+calling the B<interpolate()> method to expand sequences into text, it
+may be desirable to instead create a parse-tree using the B<parse_text()>
+method to return a tree-like structure which may contain an ordered
+list of children (each of which may be a text-string, or a similar
+tree-like structure).
+
+Pay special attention to L<"METHODS FOR PARSING AND PROCESSING"> and
+to the objects described in L<Pod::InputObjects>. The former describes
+the gory details and parameters for how to customize and extend the
+parsing behavior of B<Pod::Parser>. B<Pod::InputObjects> provides
+several objects that may all be used interchangeably as parse-trees. The
+most obvious one is the B<Pod::ParseTree> object. It defines the basic
+interface and functionality that all things trying to be a POD parse-tree
+should do. A B<Pod::ParseTree> is defined such that each "node" may be a
+text-string, or a reference to another parse-tree.  Each B<Pod::Paragraph>
+object and each B<Pod::InteriorSequence> object also supports the basic
+parse-tree interface.
+
+The B<parse_text()> method takes a given paragraph of text, and
+returns a parse-tree that contains one or more children, each of which
+may be a text-string, or an InteriorSequence object. There are also
+callback-options that may be passed to B<parse_text()> to customize
+the way it expands or transforms interior-sequences, as well as the
+returned result. These callbacks can be used to create a parse-tree
+with custom-made objects (which may or may not support the parse-tree
+interface, depending on how you choose to do it).
+
+If you wish to turn an entire POD document into a parse-tree, that process
+is fairly straightforward. The B<parse_text()> method is the key to doing
+this successfully. Every paragraph-callback (i.e. the polymorphic methods
+for B<command()>, B<verbatim()>, and B<textblock()> paragraphs) takes
+a B<Pod::Paragraph> object as an argument. Each paragraph object has a
+B<parse_tree()> method that can be used to get or set a corresponding
+parse-tree. So for each of those paragraph-callback methods, simply call
+B<parse_text()> with the options you desire, and then use the returned
+parse-tree to assign to the given paragraph object.
+
+That gives you a parse-tree for each paragraph - so now all you need is
+an ordered list of paragraphs. You can maintain that yourself as a data
+element in the object/hash. The most straightforward way would be simply
+to use an array-ref, with the desired set of custom "options" for each
+invocation of B<parse_text>. Let's assume the desired option-set is
+given by the hash C<%options>. Then we might do something like the
+following:
+
+    package MyPodParserTree;
+
+    @ISA = qw( Pod::Parser );
+
+    ...
+
+    sub begin_pod {
+        my $self = shift;
+        $self->{'-paragraphs'} = [];  ## initialize paragraph list
+    }
+
+    sub command { 
+        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
+        my $ptree = $parser->parse_text({%options}, $paragraph, ...);
+        $pod_para->parse_tree( $ptree );
+        push @{ $self->{'-paragraphs'} }, $pod_para;
+    }
+
+    sub verbatim { 
+        my ($parser, $paragraph, $line_num, $pod_para) = @_;
+        push @{ $self->{'-paragraphs'} }, $pod_para;
+    }
+
+    sub textblock { 
+        my ($parser, $paragraph, $line_num, $pod_para) = @_;
+        my $ptree = $parser->parse_text({%options}, $paragraph, ...);
+        $pod_para->parse_tree( $ptree );
+        push @{ $self->{'-paragraphs'} }, $pod_para;
+    }
+
+    ...
+
+    package main;
+    ...
+    my $parser = new MyPodParserTree(...);
+    $parser->parse_from_file(...);
+    my $paragraphs_ref = $parser->{'-paragraphs'};
+
+Of course, in this module-author's humble opinion, I'd be more inclined to
+use the existing B<Pod::ParseTree> object than a simple array. That way
+everything in it, paragraphs and sequences, all respond to the same core
+interface for all parse-tree nodes. The result would look something like:
+
+    package MyPodParserTree2;
+
+    ...
+
+    sub begin_pod {
+        my $self = shift;
+        $self->{'-ptree'} = new Pod::ParseTree;  ## initialize parse-tree
+    }
+
+    sub parse_tree {
+        ## convenience method to get/set the parse-tree for the entire POD
+        (@_ > 1)  and  $_[0]->{'-ptree'} = $_[1];
+        return $_[0]->{'-ptree'};
+    }
+
+    sub command { 
+        my ($parser, $command, $paragraph, $line_num, $pod_para) = @_;
+        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
+        $pod_para->parse_tree( $ptree );
+        $parser->parse_tree()->append( $pod_para );
+    }
+
+    sub verbatim { 
+        my ($parser, $paragraph, $line_num, $pod_para) = @_;
+        $parser->parse_tree()->append( $pod_para );
+    }
+
+    sub textblock { 
+        my ($parser, $paragraph, $line_num, $pod_para) = @_;
+        my $ptree = $parser->parse_text({<<options>>}, $paragraph, ...);
+        $pod_para->parse_tree( $ptree );
+        $parser->parse_tree()->append( $pod_para );
+    }
+
+    ...
+
+    package main;
+    ...
+    my $parser = new MyPodParserTree2(...);
+    $parser->parse_from_file(...);
+    my $ptree = $parser->parse_tree;
+    ...
+
+Now you have the entire POD document as one great big parse-tree. You
+can even use the B<-expand_seq> option to B<parse_text> to insert
+whole different kinds of objects. Just don't expect B<Pod::Parser>
+to know what to do with them after that. That will need to be in your
+code. Or, alternatively, you can insert any object you like so long as
+it conforms to the B<Pod::ParseTree> interface.
+
+One could use this to create subclasses of B<Pod::Paragraphs> and
+B<Pod::InteriorSequences> for specific commands (or to create your own
+custom node-types in the parse-tree) and add some kind of B<emit()>
+method to each custom node/subclass object in the tree. Then all you'd
+need to do is recursively walk the tree in the desired order, processing
+the children (most likely from left to right) by formatting them if
+they are text-strings, or by calling their B<emit()> method if they
+are objects/references.
+
+=head1 CAVEATS
+
+Please note that POD has the notion of "paragraphs": this is something
+starting I<after> a blank (read: empty) line, with the single exception
+of the file start, which is also starting a paragraph. That means that
+especially a command (e.g. C<=head1>) I<must> be preceded with a blank
+line; C<__END__> is I<not> a blank line.
+
+=head1 SEE ALSO
+
+L<Pod::InputObjects>, L<Pod::Select>
+
+B<Pod::InputObjects> defines POD input objects corresponding to
+command paragraphs, parse-trees, and interior-sequences.
+
+B<Pod::Select> is a subclass of B<Pod::Parser> which provides the ability
+to selectively include and/or exclude sections of a POD document from being
+translated based upon the current heading, subheading, subsubheading, etc.
+
+=for __PRIVATE__
+B<Pod::Callbacks> is a subclass of B<Pod::Parser> which gives its users
+the ability the employ I<callback functions> instead of, or in addition
+to, overriding methods of the base class.
+
+=for __PRIVATE__
+B<Pod::Select> and B<Pod::Callbacks> do not override any
+methods nor do they define any new methods with the same name. Because
+of this, they may I<both> be used (in combination) as a base class of
+the same subclass in order to combine their functionality without
+causing any namespace clashes due to multiple inheritance.
+
+=head1 AUTHOR
+
+Please report bugs using L<http://rt.cpan.org>.
+
+Brad Appleton E<lt>bradapp@enteract.comE<gt>
+
+Based on code for B<Pod::Text> written by
+Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>
+
+=head1 LICENSE
+
+Pod-Parser is free software; you can redistribute it and/or modify it
+under the terms of the Artistic License distributed with Perl version
+5.000 or (at your option) any later version. Please refer to the
+Artistic License that came with your Perl distribution for more
+details. If your version of Perl was not distributed under the
+terms of the Artistic License, than you may distribute PodParser
+under the same terms as Perl itself.
+
+=cut
+
+1;
+# vim: ts=4 sw=4 et
index e8dc001..5f93b88 100644 (file)
-# Pod::PlainText -- Convert POD data to formatted ASCII text.\r
-# $Id: Text.pm,v 2.1 1999/09/20 11:53:33 eagle Exp $\r
-#\r
-# Copyright 1999-2000 by Russ Allbery <rra@stanford.edu>\r
-#\r
-# This program is free software; you can redistribute it and/or modify it\r
-# under the same terms as Perl itself.\r
-#\r
-# This module is intended to be a replacement for Pod::Text, and attempts to\r
-# match its output except for some specific circumstances where other\r
-# decisions seemed to produce better output.  It uses Pod::Parser and is\r
-# designed to be very easy to subclass.\r
-\r
-############################################################################\r
-# Modules and declarations\r
-############################################################################\r
-\r
-package Pod::PlainText;\r
-use strict;\r
-\r
-require 5.005;\r
-\r
-use Carp qw(carp croak);\r
-use Pod::Select ();\r
-\r
-use vars qw(@ISA %ESCAPES $VERSION);\r
-\r
-# We inherit from Pod::Select instead of Pod::Parser so that we can be used\r
-# by Pod::Usage.\r
-@ISA = qw(Pod::Select);\r
-\r
-$VERSION = '2.06';\r
-\r
-BEGIN {\r
-   if ($] < 5.006) {\r
-      require Symbol;\r
-      import Symbol;\r
-   }\r
-}\r
-\r
-############################################################################\r
-# Table of supported E<> escapes\r
-############################################################################\r
-\r
-# This table is taken near verbatim from Pod::PlainText in Pod::Parser,\r
-# which got it near verbatim from the original Pod::Text.  It is therefore\r
-# credited to Tom Christiansen, and I'm glad I didn't have to write it.  :)\r
-%ESCAPES = (\r
-    'amp'       =>    '&',      # ampersand\r
-    'lt'        =>    '<',      # left chevron, less-than\r
-    'gt'        =>    '>',      # right chevron, greater-than\r
-    'quot'      =>    '"',      # double quote\r
-\r
-    "Aacute"    =>    "\xC1",   # capital A, acute accent\r
-    "aacute"    =>    "\xE1",   # small a, acute accent\r
-    "Acirc"     =>    "\xC2",   # capital A, circumflex accent\r
-    "acirc"     =>    "\xE2",   # small a, circumflex accent\r
-    "AElig"     =>    "\xC6",   # capital AE diphthong (ligature)\r
-    "aelig"     =>    "\xE6",   # small ae diphthong (ligature)\r
-    "Agrave"    =>    "\xC0",   # capital A, grave accent\r
-    "agrave"    =>    "\xE0",   # small a, grave accent\r
-    "Aring"     =>    "\xC5",   # capital A, ring\r
-    "aring"     =>    "\xE5",   # small a, ring\r
-    "Atilde"    =>    "\xC3",   # capital A, tilde\r
-    "atilde"    =>    "\xE3",   # small a, tilde\r
-    "Auml"      =>    "\xC4",   # capital A, dieresis or umlaut mark\r
-    "auml"      =>    "\xE4",   # small a, dieresis or umlaut mark\r
-    "Ccedil"    =>    "\xC7",   # capital C, cedilla\r
-    "ccedil"    =>    "\xE7",   # small c, cedilla\r
-    "Eacute"    =>    "\xC9",   # capital E, acute accent\r
-    "eacute"    =>    "\xE9",   # small e, acute accent\r
-    "Ecirc"     =>    "\xCA",   # capital E, circumflex accent\r
-    "ecirc"     =>    "\xEA",   # small e, circumflex accent\r
-    "Egrave"    =>    "\xC8",   # capital E, grave accent\r
-    "egrave"    =>    "\xE8",   # small e, grave accent\r
-    "ETH"       =>    "\xD0",   # capital Eth, Icelandic\r
-    "eth"       =>    "\xF0",   # small eth, Icelandic\r
-    "Euml"      =>    "\xCB",   # capital E, dieresis or umlaut mark\r
-    "euml"      =>    "\xEB",   # small e, dieresis or umlaut mark\r
-    "Iacute"    =>    "\xCD",   # capital I, acute accent\r
-    "iacute"    =>    "\xED",   # small i, acute accent\r
-    "Icirc"     =>    "\xCE",   # capital I, circumflex accent\r
-    "icirc"     =>    "\xEE",   # small i, circumflex accent\r
-    "Igrave"    =>    "\xCD",   # capital I, grave accent\r
-    "igrave"    =>    "\xED",   # small i, grave accent\r
-    "Iuml"      =>    "\xCF",   # capital I, dieresis or umlaut mark\r
-    "iuml"      =>    "\xEF",   # small i, dieresis or umlaut mark\r
-    "Ntilde"    =>    "\xD1",   # capital N, tilde\r
-    "ntilde"    =>    "\xF1",   # small n, tilde\r
-    "Oacute"    =>    "\xD3",   # capital O, acute accent\r
-    "oacute"    =>    "\xF3",   # small o, acute accent\r
-    "Ocirc"     =>    "\xD4",   # capital O, circumflex accent\r
-    "ocirc"     =>    "\xF4",   # small o, circumflex accent\r
-    "Ograve"    =>    "\xD2",   # capital O, grave accent\r
-    "ograve"    =>    "\xF2",   # small o, grave accent\r
-    "Oslash"    =>    "\xD8",   # capital O, slash\r
-    "oslash"    =>    "\xF8",   # small o, slash\r
-    "Otilde"    =>    "\xD5",   # capital O, tilde\r
-    "otilde"    =>    "\xF5",   # small o, tilde\r
-    "Ouml"      =>    "\xD6",   # capital O, dieresis or umlaut mark\r
-    "ouml"      =>    "\xF6",   # small o, dieresis or umlaut mark\r
-    "szlig"     =>    "\xDF",   # small sharp s, German (sz ligature)\r
-    "THORN"     =>    "\xDE",   # capital THORN, Icelandic\r
-    "thorn"     =>    "\xFE",   # small thorn, Icelandic\r
-    "Uacute"    =>    "\xDA",   # capital U, acute accent\r
-    "uacute"    =>    "\xFA",   # small u, acute accent\r
-    "Ucirc"     =>    "\xDB",   # capital U, circumflex accent\r
-    "ucirc"     =>    "\xFB",   # small u, circumflex accent\r
-    "Ugrave"    =>    "\xD9",   # capital U, grave accent\r
-    "ugrave"    =>    "\xF9",   # small u, grave accent\r
-    "Uuml"      =>    "\xDC",   # capital U, dieresis or umlaut mark\r
-    "uuml"      =>    "\xFC",   # small u, dieresis or umlaut mark\r
-    "Yacute"    =>    "\xDD",   # capital Y, acute accent\r
-    "yacute"    =>    "\xFD",   # small y, acute accent\r
-    "yuml"      =>    "\xFF",   # small y, dieresis or umlaut mark\r
-\r
-    "lchevron"  =>    "\xAB",   # left chevron (double less than)\r
-    "rchevron"  =>    "\xBB",   # right chevron (double greater than)\r
-);\r
-\r
-\r
-############################################################################\r
-# Initialization\r
-############################################################################\r
-\r
-# Initialize the object.  Must be sure to call our parent initializer.\r
-sub initialize {\r
-    my $self = shift;\r
-\r
-    $$self{alt}      = 0  unless defined $$self{alt};\r
-    $$self{indent}   = 4  unless defined $$self{indent};\r
-    $$self{loose}    = 0  unless defined $$self{loose};\r
-    $$self{sentence} = 0  unless defined $$self{sentence};\r
-    $$self{width}    = 76 unless defined $$self{width};\r
-\r
-    $$self{INDENTS}  = [];              # Stack of indentations.\r
-    $$self{MARGIN}   = $$self{indent};  # Current left margin in spaces.\r
-\r
-    return $self->SUPER::initialize;\r
-}\r
-\r
-\r
-############################################################################\r
-# Core overrides\r
-############################################################################\r
-\r
-# Called for each command paragraph.  Gets the command, the associated\r
-# paragraph, the line number, and a Pod::Paragraph object.  Just dispatches\r
-# the command to a method named the same as the command.  =cut is handled\r
-# internally by Pod::Parser.\r
-sub command {\r
-    my $self = shift;\r
-    my $command = shift;\r
-    return if $command eq 'pod';\r
-    return if ($$self{EXCLUDE} && $command ne 'end');\r
-    if (defined $$self{ITEM}) {\r
-      $self->item ("\n");\r
-      local $_ = "\n";\r
-      $self->output($_) if($command eq 'back');\r
-    }\r
-    $command = 'cmd_' . $command;\r
-    return $self->$command (@_);\r
-}\r
-\r
-# Called for a verbatim paragraph.  Gets the paragraph, the line number, and\r
-# a Pod::Paragraph object.  Just output it verbatim, but with tabs converted\r
-# to spaces.\r
-sub verbatim {\r
-    my $self = shift;\r
-    return if $$self{EXCLUDE};\r
-    $self->item if defined $$self{ITEM};\r
-    local $_ = shift;\r
-    return if /^\s*$/;\r
-    s/^(\s*\S+)/(' ' x $$self{MARGIN}) . $1/gme;\r
-    return $self->output($_);\r
-}\r
-\r
-# Called for a regular text block.  Gets the paragraph, the line number, and\r
-# a Pod::Paragraph object.  Perform interpolation and output the results.\r
-sub textblock {\r
-    my $self = shift;\r
-    return if $$self{EXCLUDE};\r
-    if($$self{VERBATIM}) {\r
-      $self->output($_[0]);\r
-      return;\r
-    }\r
-    local $_ = shift;\r
-    my $line = shift;\r
-\r
-    # Perform a little magic to collapse multiple L<> references.  This is\r
-    # here mostly for backwards-compatibility.  We'll just rewrite the whole\r
-    # thing into actual text at this part, bypassing the whole internal\r
-    # sequence parsing thing.\r
-    s{\r
-        (\r
-          L<                    # A link of the form L</something>.\r
-              /\r
-              (\r
-                  [:\w]+        # The item has to be a simple word...\r
-                  (\(\))?       # ...or simple function.\r
-              )\r
-          >\r
-          (\r
-              ,?\s+(and\s+)?    # Allow lots of them, conjuncted.\r
-              L<  \r
-                  /\r
-                  (\r
-                      [:\w]+\r
-                      (\(\))?\r
-                  )\r
-              >\r
-          )+\r
-        )\r
-    } {\r
-        local $_ = $1;\r
-        s%L</([^>]+)>%$1%g;\r
-        my @items = split /(?:,?\s+(?:and\s+)?)/;\r
-        my $string = "the ";\r
-        my $i;\r
-        for ($i = 0; $i < @items; $i++) {\r
-            $string .= $items[$i];\r
-            $string .= ", " if @items > 2 && $i != $#items;\r
-            $string .= " and " if ($i == $#items - 1);\r
-        }\r
-        $string .= " entries elsewhere in this document";\r
-        $string;\r
-    }gex;\r
-\r
-    # Now actually interpolate and output the paragraph.\r
-    $_ = $self->interpolate ($_, $line);\r
-    s/\s*$/\n/s;\r
-    if (defined $$self{ITEM}) {\r
-        $self->item ($_ . "\n");\r
-    } else {\r
-        $self->output ($self->reformat ($_ . "\n"));\r
-    }\r
-}\r
-\r
-# Called for an interior sequence.  Gets the command, argument, and a\r
-# Pod::InteriorSequence object and is expected to return the resulting text.\r
-# Calls code, bold, italic, file, and link to handle those types of\r
-# sequences, and handles S<>, E<>, X<>, and Z<> directly.\r
-sub interior_sequence {\r
-    my $self = shift;\r
-    my $command = shift;\r
-    local $_ = shift;\r
-    return '' if ($command eq 'X' || $command eq 'Z');\r
-\r
-    # Expand escapes into the actual character now, carping if invalid.\r
-    if ($command eq 'E') {\r
-        return $ESCAPES{$_} if defined $ESCAPES{$_};\r
-        carp "Unknown escape: E<$_>";\r
-        return "E<$_>";\r
-    }\r
-\r
-    # For all the other sequences, empty content produces no output.\r
-    return if $_ eq '';\r
-\r
-    # For S<>, compress all internal whitespace and then map spaces to \01.\r
-    # When we output the text, we'll map this back.\r
-    if ($command eq 'S') {\r
-        s/\s{2,}/ /g;\r
-        tr/ /\01/;\r
-        return $_;\r
-    }\r
-\r
-    # Anything else needs to get dispatched to another method.\r
-    if    ($command eq 'B') { return $self->seq_b ($_) }\r
-    elsif ($command eq 'C') { return $self->seq_c ($_) }\r
-    elsif ($command eq 'F') { return $self->seq_f ($_) }\r
-    elsif ($command eq 'I') { return $self->seq_i ($_) }\r
-    elsif ($command eq 'L') { return $self->seq_l ($_) }\r
-    else { carp "Unknown sequence $command<$_>" }\r
-}\r
-\r
-# Called for each paragraph that's actually part of the POD.  We take\r
-# advantage of this opportunity to untabify the input.\r
-sub preprocess_paragraph {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me;\r
-    return $_;\r
-}\r
-\r
-\r
-############################################################################\r
-# Command paragraphs\r
-############################################################################\r
-\r
-# All command paragraphs take the paragraph and the line number.\r
-\r
-# First level heading.\r
-sub cmd_head1 {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    s/\s+$//s;\r
-    $_ = $self->interpolate ($_, shift);\r
-    if ($$self{alt}) {\r
-        $self->output ("\n==== $_ ====\n\n");\r
-    } else {\r
-        $_ .= "\n" if $$self{loose};\r
-        $self->output ($_ . "\n");\r
-    }\r
-}\r
-\r
-# Second level heading.\r
-sub cmd_head2 {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    s/\s+$//s;\r
-    $_ = $self->interpolate ($_, shift);\r
-    if ($$self{alt}) {\r
-        $self->output ("\n==   $_   ==\n\n");\r
-    } else {\r
-        $_ .= "\n" if $$self{loose};\r
-        $self->output (' ' x ($$self{indent} / 2) . $_ . "\n");\r
-    }\r
-}\r
-\r
-# third level heading - not strictly perlpodspec compliant\r
-sub cmd_head3 {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    s/\s+$//s;\r
-    $_ = $self->interpolate ($_, shift);\r
-    if ($$self{alt}) {\r
-        $self->output ("\n= $_ =\n");\r
-    } else {\r
-        $_ .= "\n" if $$self{loose};\r
-        $self->output (' ' x ($$self{indent}) . $_ . "\n");\r
-    }\r
-}\r
-\r
-# fourth level heading - not strictly perlpodspec compliant\r
-# just like head3\r
-*cmd_head4 = \&cmd_head3;\r
-\r
-# Start a list.\r
-sub cmd_over {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} }\r
-    push (@{ $$self{INDENTS} }, $$self{MARGIN});\r
-    $$self{MARGIN} += ($_ + 0);\r
-}\r
-\r
-# End a list.\r
-sub cmd_back {\r
-    my $self = shift;\r
-    $$self{MARGIN} = pop @{ $$self{INDENTS} };\r
-    unless (defined $$self{MARGIN}) {\r
-        carp 'Unmatched =back';\r
-        $$self{MARGIN} = $$self{indent};\r
-    }\r
-}\r
-\r
-# An individual list item.\r
-sub cmd_item {\r
-    my $self = shift;\r
-    if (defined $$self{ITEM}) { $self->item }\r
-    local $_ = shift;\r
-    s/\s+$//s;\r
-    $$self{ITEM} = $self->interpolate ($_);\r
-}\r
-\r
-# Begin a block for a particular translator.  Setting VERBATIM triggers\r
-# special handling in textblock().\r
-sub cmd_begin {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    my ($kind) = /^(\S+)/ or return;\r
-    if ($kind eq 'text') {\r
-        $$self{VERBATIM} = 1;\r
-    } else {\r
-        $$self{EXCLUDE} = 1;\r
-    }\r
-}\r
-\r
-# End a block for a particular translator.  We assume that all =begin/=end\r
-# pairs are properly closed.\r
-sub cmd_end {\r
-    my $self = shift;\r
-    $$self{EXCLUDE} = 0;\r
-    $$self{VERBATIM} = 0;\r
-}\r
-\r
-# One paragraph for a particular translator.  Ignore it unless it's intended\r
-# for text, in which case we treat it as a verbatim text block.\r
-sub cmd_for {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    my $line = shift;\r
-    return unless s/^text\b[ \t]*\r?\n?//;\r
-    $self->verbatim ($_, $line);\r
-}\r
-\r
-# just a dummy method for the time being\r
-sub cmd_encoding {\r
-  return;\r
-}\r
-\r
-############################################################################\r
-# Interior sequences\r
-############################################################################\r
-\r
-# The simple formatting ones.  These are here mostly so that subclasses can\r
-# override them and do more complicated things.\r
-sub seq_b { return $_[0]{alt} ? "``$_[1]''" : $_[1] }\r
-sub seq_c { return $_[0]{alt} ? "``$_[1]''" : "`$_[1]'" }\r
-sub seq_f { return $_[0]{alt} ? "\"$_[1]\"" : $_[1] }\r
-sub seq_i { return '*' . $_[1] . '*' }\r
-\r
-# The complicated one.  Handle links.  Since this is plain text, we can't\r
-# actually make any real links, so this is all to figure out what text we\r
-# print out.\r
-sub seq_l {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-\r
-    # Smash whitespace in case we were split across multiple lines.\r
-    s/\s+/ /g;\r
-\r
-    # If we were given any explicit text, just output it.\r
-    if (/^([^|]+)\|/) { return $1 }\r
-\r
-    # Okay, leading and trailing whitespace isn't important; get rid of it.\r
-    s/^\s+//;\r
-    s/\s+$//;\r
-\r
-    # Default to using the whole content of the link entry as a section\r
-    # name.  Note that L<manpage/> forces a manpage interpretation, as does\r
-    # something looking like L<manpage(section)>.  The latter is an\r
-    # enhancement over the original Pod::Text.\r
-    my ($manpage, $section) = ('', $_);\r
-    if (/^(?:https?|ftp|news):/) {\r
-        # a URL\r
-        return $_;\r
-    } elsif (/^"\s*(.*?)\s*"$/) {\r
-        $section = '"' . $1 . '"';\r
-    } elsif (m/^[-:.\w]+(?:\(\S+\))?$/) {\r
-        ($manpage, $section) = ($_, '');\r
-    } elsif (m{/}) {\r
-        ($manpage, $section) = split (/\s*\/\s*/, $_, 2);\r
-    }\r
-\r
-    my $text = '';\r
-    # Now build the actual output text.\r
-    if (!length $section) {\r
-        $text = "the $manpage manpage" if length $manpage;\r
-    } elsif ($section =~ /^[:\w]+(?:\(\))?/) {\r
-        $text .= 'the ' . $section . ' entry';\r
-        $text .= (length $manpage) ? " in the $manpage manpage"\r
-                                   : ' elsewhere in this document';\r
-    } else {\r
-        $section =~ s/^\"\s*//;\r
-        $section =~ s/\s*\"$//;\r
-        $text .= 'the section on "' . $section . '"';\r
-        $text .= " in the $manpage manpage" if length $manpage;\r
-    }\r
-    return $text;\r
-}\r
-\r
-\r
-############################################################################\r
-# List handling\r
-############################################################################\r
-\r
-# This method is called whenever an =item command is complete (in other\r
-# words, we've seen its associated paragraph or know for certain that it\r
-# doesn't have one).  It gets the paragraph associated with the item as an\r
-# argument.  If that argument is empty, just output the item tag; if it\r
-# contains a newline, output the item tag followed by the newline.\r
-# Otherwise, see if there's enough room for us to output the item tag in the\r
-# margin of the text or if we have to put it on a separate line.\r
-sub item {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    my $tag = $$self{ITEM};\r
-    unless (defined $tag) {\r
-        carp 'item called without tag';\r
-        return;\r
-    }\r
-    undef $$self{ITEM};\r
-    my $indent = $$self{INDENTS}[-1];\r
-    unless (defined $indent) { $indent = $$self{indent} }\r
-    my $space = ' ' x $indent;\r
-    $space =~ s/^ /:/ if $$self{alt};\r
-    if (!$_ || /^\s+$/ || ($$self{MARGIN} - $indent < length ($tag) + 1)) {\r
-        my $margin = $$self{MARGIN};\r
-        $$self{MARGIN} = $indent;\r
-        my $output = $self->reformat ($tag);\r
-        $output =~ s/[\r\n]*$/\n/;\r
-        $self->output ($output);\r
-        $$self{MARGIN} = $margin;\r
-        $self->output ($self->reformat ($_)) if /\S/;\r
-    } else {\r
-        $_ = $self->reformat ($_);\r
-        s/^ /:/ if ($$self{alt} && $indent > 0);\r
-        my $tagspace = ' ' x length $tag;\r
-        s/^($space)$tagspace/$1$tag/ or carp 'Bizarre space in item';\r
-        $self->output ($_);\r
-    }\r
-}\r
-\r
-\r
-############################################################################\r
-# Output formatting\r
-############################################################################\r
-\r
-# Wrap a line, indenting by the current left margin.  We can't use\r
-# Text::Wrap because it plays games with tabs.  We can't use formline, even\r
-# though we'd really like to, because it screws up non-printing characters.\r
-# So we have to do the wrapping ourselves.\r
-sub wrap {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-    my $output = '';\r
-    my $spaces = ' ' x $$self{MARGIN};\r
-    my $width = $$self{width} - $$self{MARGIN};\r
-    while (length > $width) {\r
-        if (s/^([^\r\n]{0,$width})\s+// || s/^([^\r\n]{$width})//) {\r
-            $output .= $spaces . $1 . "\n";\r
-        } else {\r
-            last;\r
-        }\r
-    }\r
-    $output .= $spaces . $_;\r
-    $output =~ s/\s+$/\n\n/;\r
-    return $output;\r
-}\r
-\r
-# Reformat a paragraph of text for the current margin.  Takes the text to\r
-# reformat and returns the formatted text.\r
-sub reformat {\r
-    my $self = shift;\r
-    local $_ = shift;\r
-\r
-    # If we're trying to preserve two spaces after sentences, do some\r
-    # munging to support that.  Otherwise, smash all repeated whitespace.\r
-    if ($$self{sentence}) {\r
-        s/ +$//mg;\r
-        s/\.\r?\n/. \n/g;\r
-        s/[\r\n]+/ /g;\r
-        s/   +/  /g;\r
-    } else {\r
-        s/\s+/ /g;\r
-    }\r
-    return $self->wrap($_);\r
-}\r
-\r
-# Output text to the output device.\r
-sub output { $_[1] =~ tr/\01/ /; print { $_[0]->output_handle } $_[1] }\r
-\r
-\r
-############################################################################\r
-# Backwards compatibility\r
-############################################################################\r
-\r
-# The old Pod::Text module did everything in a pod2text() function.  This\r
-# tries to provide the same interface for legacy applications.\r
-sub pod2text {\r
-    my @args;\r
-\r
-    # This is really ugly; I hate doing option parsing in the middle of a\r
-    # module.  But the old Pod::Text module supported passing flags to its\r
-    # entry function, so handle -a and -<number>.\r
-    while ($_[0] =~ /^-/) {\r
-        my $flag = shift;\r
-        if    ($flag eq '-a')       { push (@args, alt => 1)    }\r
-        elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) }\r
-        else {\r
-            unshift (@_, $flag);\r
-            last;\r
-        }\r
-    }\r
-\r
-    # Now that we know what arguments we're using, create the parser.\r
-    my $parser = Pod::PlainText->new (@args);\r
-\r
-    # If two arguments were given, the second argument is going to be a file\r
-    # handle.  That means we want to call parse_from_filehandle(), which\r
-    # means we need to turn the first argument into a file handle.  Magic\r
-    # open will handle the <&STDIN case automagically.\r
-    if (defined $_[1]) {\r
-        my $infh;\r
-        if ($] < 5.006) {\r
-          $infh = gensym();\r
-        }\r
-        unless (open ($infh, $_[0])) {\r
-            croak ("Can't open $_[0] for reading: $!\n");\r
-        }\r
-        $_[0] = $infh;\r
-        return $parser->parse_from_filehandle (@_);\r
-    } else {\r
-        return $parser->parse_from_file (@_);\r
-    }\r
-}\r
-\r
-\r
-############################################################################\r
-# Module return value and documentation\r
-############################################################################\r
-\r
-1;\r
-__END__\r
-\r
-=head1 NAME\r
-\r
-Pod::PlainText - Convert POD data to formatted ASCII text\r
-\r
-=head1 SYNOPSIS\r
-\r
-    use Pod::PlainText;\r
-    my $parser = Pod::PlainText->new (sentence => 0, width => 78);\r
-\r
-    # Read POD from STDIN and write to STDOUT.\r
-    $parser->parse_from_filehandle;\r
-\r
-    # Read POD from file.pod and write to file.txt.\r
-    $parser->parse_from_file ('file.pod', 'file.txt');\r
-\r
-=head1 DESCRIPTION\r
-\r
-Pod::PlainText is a module that can convert documentation in the POD format (the\r
-preferred language for documenting Perl) into formatted ASCII.  It uses no\r
-special formatting controls or codes whatsoever, and its output is therefore\r
-suitable for nearly any device.\r
-\r
-As a derived class from Pod::Parser, Pod::PlainText supports the same methods and\r
-interfaces.  See L<Pod::Parser> for all the details; briefly, one creates a\r
-new parser with C<Pod::PlainText-E<gt>new()> and then calls either\r
-parse_from_filehandle() or parse_from_file().\r
-\r
-new() can take options, in the form of key/value pairs, that control the\r
-behavior of the parser.  The currently recognized options are:\r
-\r
-=over 4\r
-\r
-=item alt\r
-\r
-If set to a true value, selects an alternate output format that, among other\r
-things, uses a different heading style and marks C<=item> entries with a\r
-colon in the left margin.  Defaults to false.\r
-\r
-=item indent\r
-\r
-The number of spaces to indent regular text, and the default indentation for\r
-C<=over> blocks.  Defaults to 4.\r
-\r
-=item loose\r
-\r
-If set to a true value, a blank line is printed after a C<=headN> headings.\r
-If set to false (the default), no blank line is printed after C<=headN>.\r
-This is the default because it's the expected formatting for manual pages;\r
-if you're formatting arbitrary text documents, setting this to true may\r
-result in more pleasing output.\r
-\r
-=item sentence\r
-\r
-If set to a true value, Pod::PlainText will assume that each sentence ends in two\r
-spaces, and will try to preserve that spacing.  If set to false, all\r
-consecutive whitespace in non-verbatim paragraphs is compressed into a\r
-single space.  Defaults to true.\r
-\r
-=item width\r
-\r
-The column at which to wrap text on the right-hand side.  Defaults to 76.\r
-\r
-=back\r
-\r
-The standard Pod::Parser method parse_from_filehandle() takes up to two\r
-arguments, the first being the file handle to read POD from and the second\r
-being the file handle to write the formatted output to.  The first defaults\r
-to STDIN if not given, and the second defaults to STDOUT.  The method\r
-parse_from_file() is almost identical, except that its two arguments are the\r
-input and output disk files instead.  See L<Pod::Parser> for the specific\r
-details.\r
-\r
-=head1 DIAGNOSTICS\r
-\r
-=over 4\r
-\r
-=item Bizarre space in item\r
-\r
-(W) Something has gone wrong in internal C<=item> processing.  This message\r
-indicates a bug in Pod::PlainText; you should never see it.\r
-\r
-=item Can't open %s for reading: %s\r
-\r
-(F) Pod::PlainText was invoked via the compatibility mode pod2text() interface\r
-and the input file it was given could not be opened.\r
-\r
-=item Unknown escape: %s\r
-\r
-(W) The POD source contained an C<EE<lt>E<gt>> escape that Pod::PlainText didn't\r
-know about.\r
-\r
-=item Unknown sequence: %s\r
-\r
-(W) The POD source contained a non-standard internal sequence (something of\r
-the form C<XE<lt>E<gt>>) that Pod::PlainText didn't know about.\r
-\r
-=item Unmatched =back\r
-\r
-(W) Pod::PlainText encountered a C<=back> command that didn't correspond to an\r
-C<=over> command.\r
-\r
-=back\r
-\r
-=head1 RESTRICTIONS\r
-\r
-Embedded Ctrl-As (octal 001) in the input will be mapped to spaces on\r
-output, due to an internal implementation detail.\r
-\r
-=head1 NOTES\r
-\r
-This is a replacement for an earlier Pod::Text module written by Tom\r
-Christiansen.  It has a revamped interface, since it now uses Pod::Parser,\r
-but an interface roughly compatible with the old Pod::Text::pod2text()\r
-function is still available.  Please change to the new calling convention,\r
-though.\r
-\r
-The original Pod::Text contained code to do formatting via termcap\r
-sequences, although it wasn't turned on by default and it was problematic to\r
-get it to work at all.  This rewrite doesn't even try to do that, but a\r
-subclass of it does.  Look for L<Pod::Text::Termcap|Pod::Text::Termcap>.\r
-\r
-=head1 SEE ALSO\r
-\r
-B<Pod::PlainText> is part of the L<Pod::Parser> distribution.\r
-\r
-L<Pod::Parser|Pod::Parser>, L<Pod::Text::Termcap|Pod::Text::Termcap>,\r
-pod2text(1)\r
-\r
-=head1 AUTHOR\r
-\r
-Please report bugs using L<http://rt.cpan.org>.\r
-\r
-Russ Allbery E<lt>rra@stanford.eduE<gt>, based I<very> heavily on the\r
-original Pod::Text by Tom Christiansen E<lt>tchrist@mox.perl.comE<gt> and\r
-its conversion to Pod::Parser by Brad Appleton\r
-E<lt>bradapp@enteract.comE<gt>.\r
-\r
-=cut\r
+# Pod::PlainText -- Convert POD data to formatted ASCII text.
+# $Id: Text.pm,v 2.1 1999/09/20 11:53:33 eagle Exp $
+#
+# Copyright 1999-2000 by Russ Allbery <rra@stanford.edu>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+#
+# This module is intended to be a replacement for Pod::Text, and attempts to
+# match its output except for some specific circumstances where other
+# decisions seemed to produce better output.  It uses Pod::Parser and is
+# designed to be very easy to subclass.
+
+############################################################################
+# Modules and declarations
+############################################################################
+
+package Pod::PlainText;
+use strict;
+
+require 5.005;
+
+use Carp qw(carp croak);
+use Pod::Select ();
+
+use vars qw(@ISA %ESCAPES $VERSION);
+
+# We inherit from Pod::Select instead of Pod::Parser so that we can be used
+# by Pod::Usage.
+@ISA = qw(Pod::Select);
+
+$VERSION = '2.06';
+
+BEGIN {
+   if ($] < 5.006) {
+      require Symbol;
+      import Symbol;
+   }
+}
+
+############################################################################
+# Table of supported E<> escapes
+############################################################################
+
+# This table is taken near verbatim from Pod::PlainText in Pod::Parser,
+# which got it near verbatim from the original Pod::Text.  It is therefore
+# credited to Tom Christiansen, and I'm glad I didn't have to write it.  :)
+%ESCAPES = (
+    'amp'       =>    '&',      # ampersand
+    'lt'        =>    '<',      # left chevron, less-than
+    'gt'        =>    '>',      # right chevron, greater-than
+    'quot'      =>    '"',      # double quote
+
+    "Aacute"    =>    "\xC1",   # capital A, acute accent
+   &nbs