diff options
Diffstat (limited to 'contrib/perl5/lib/Pod')
-rw-r--r-- | contrib/perl5/lib/Pod/Checker.pm | 1242 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Find.pm | 445 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Functions.pm | 302 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Html.pm | 2025 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/InputObjects.pm | 933 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/LaTeX.pm | 1591 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Man.pm | 1387 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/ParseUtils.pm | 851 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Parser.pm | 1768 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Plainer.pm | 69 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Select.pm | 751 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Text.pm | 827 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Text/Color.pm | 128 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Text/Overstrike.pm | 160 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Text/Termcap.pm | 145 | ||||
-rw-r--r-- | contrib/perl5/lib/Pod/Usage.pm | 559 |
16 files changed, 0 insertions, 13183 deletions
diff --git a/contrib/perl5/lib/Pod/Checker.pm b/contrib/perl5/lib/Pod/Checker.pm deleted file mode 100644 index 0863c80..0000000 --- a/contrib/perl5/lib/Pod/Checker.pm +++ /dev/null @@ -1,1242 +0,0 @@ -############################################################################# -# Pod/Checker.pm -- check pod documents for syntax errors -# -# Copyright (C) 1994-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::Checker; - -use vars qw($VERSION); -$VERSION = 1.2; ## Current version of this package -require 5.005; ## requires this Perl version or later - -use Pod::ParseUtils; ## for hyperlinks and lists - -=head1 NAME - -Pod::Checker, podchecker() - check pod documents for syntax errors - -=head1 SYNOPSIS - - use Pod::Checker; - - $syntax_okay = podchecker($filepath, $outputpath, %options); - - my $checker = new Pod::Checker %options; - $checker->parse_from_file($filepath, \*STDERR); - -=head1 OPTIONS/ARGUMENTS - -C<$filepath> is the input POD to read and C<$outputpath> is -where to write POD syntax error messages. Either argument may be a scalar -indicating a file-path, or else a reference to an open filehandle. -If unspecified, the input-file it defaults to C<\*STDIN>, and -the output-file defaults to C<\*STDERR>. - -=head2 podchecker() - -This function can take a hash of options: - -=over 4 - -=item B<-warnings> =E<gt> I<val> - -Turn warnings on/off. I<val> is usually 1 for on, but higher values -trigger additional warnings. See L<"Warnings">. - -=back - -=head1 DESCRIPTION - -B<podchecker> will perform syntax checking of Perl5 POD format documentation. - -I<NOTE THAT THIS MODULE IS CURRENTLY IN THE BETA STAGE!> - -It is hoped that curious/ambitious user will help flesh out and add the -additional features they wish to see in B<Pod::Checker> and B<podchecker> -and verify that the checks are consistent with L<perlpod>. - -The following checks are currently preformed: - -=over 4 - -=item * - -Unknown '=xxxx' commands, unknown 'XE<lt>...E<gt>' interior-sequences, -and unterminated interior sequences. - -=item * - -Check for proper balancing of C<=begin> and C<=end>. The contents of such -a block are generally ignored, i.e. no syntax checks are performed. - -=item * - -Check for proper nesting and balancing of C<=over>, C<=item> and C<=back>. - -=item * - -Check for same nested interior-sequences (e.g. -C<LE<lt>...LE<lt>...E<gt>...E<gt>>). - -=item * - -Check for malformed or nonexisting entities C<EE<lt>...E<gt>>. - -=item * - -Check for correct syntax of hyperlinks C<LE<lt>...E<gt>>. See L<perlpod> -for details. - -=item * - -Check for unresolved document-internal links. This check may also reveal -misspelled links that seem to be internal links but should be links -to something else. - -=back - -=head1 DIAGNOSTICS - -=head2 Errors - -=over 4 - -=item * empty =headn - -A heading (C<=head1> or C<=head2>) without any text? That ain't no -heading! - -=item * =over on line I<N> without closing =back - -The C<=over> command does not have a corresponding C<=back> before the -next heading (C<=head1> or C<=head2>) or the end of the file. - -=item * =item without previous =over - -=item * =back without previous =over - -An C<=item> or C<=back> command has been found outside a -C<=over>/C<=back> block. - -=item * No argument for =begin - -A C<=begin> command was found that is not followed by the formatter -specification. - -=item * =end without =begin - -A standalone C<=end> command was found. - -=item * Nested =begin's - -There were at least two consecutive C<=begin> commands without -the corresponding C<=end>. Only one C<=begin> may be active at -a time. - -=item * =for without formatter specification - -There is no specification of the formatter after the C<=for> command. - -=item * unresolved internal link I<NAME> - -The given link to I<NAME> does not have a matching node in the current -POD. This also happend when a single word node name is not enclosed in -C<"">. - -=item * Unknown command "I<CMD>" - -An invalid POD command has been found. Valid are C<=head1>, C<=head2>, -C<=over>, C<=item>, C<=back>, C<=begin>, C<=end>, C<=for>, C<=pod>, -C<=cut> - -=item * Unknown interior-sequence "I<SEQ>" - -An invalid markup command has been encountered. Valid are: -C<BE<lt>E<gt>>, C<CE<lt>E<gt>>, C<EE<lt>E<gt>>, C<FE<lt>E<gt>>, -C<IE<lt>E<gt>>, C<LE<lt>E<gt>>, C<SE<lt>E<gt>>, C<XE<lt>E<gt>>, -C<ZE<lt>E<gt>> - -=item * nested commands I<CMD>E<lt>...I<CMD>E<lt>...E<gt>...E<gt> - -Two nested identical markup commands have been found. Generally this -does not make sense. - -=item * garbled entity I<STRING> - -The I<STRING> found cannot be interpreted as a character entity. - -=item * Entity number out of range - -An entity specified by number (dec, hex, oct) is out of range (1-255). - -=item * malformed link LE<lt>E<gt> - -The link found cannot be parsed because it does not conform to the -syntax described in L<perlpod>. - -=item * nonempty ZE<lt>E<gt> - -The C<ZE<lt>E<gt>> sequence is supposed to be empty. - -=item * empty XE<lt>E<gt> - -The index entry specified contains nothing but whitespace. - -=item * Spurious text after =pod / =cut - -The commands C<=pod> and C<=cut> do not take any arguments. - -=item * Spurious character(s) after =back - -The C<=back> command does not take any arguments. - -=back - -=head2 Warnings - -These may not necessarily cause trouble, but indicate mediocre style. - -=over 4 - -=item * multiple occurence of link target I<name> - -The POD file has some C<=item> and/or C<=head> commands that have -the same text. Potential hyperlinks to such a text cannot be unique then. - -=item * line containing nothing but whitespace in paragraph - -There is some whitespace on a seemingly empty line. POD is very sensitive -to such things, so this is flagged. B<vi> users switch on the B<list> -option to avoid this problem. - -=begin _disabled_ - -=item * file does not start with =head - -The file starts with a different POD directive than head. -This is most probably something you do not want. - -=end _disabled_ - -=item * previous =item has no contents - -There is a list C<=item> right above the flagged line that has no -text contents. You probably want to delete empty items. - -=item * preceding non-item paragraph(s) - -A list introduced by C<=over> starts with a text or verbatim paragraph, -but continues with C<=item>s. Move the non-item paragraph out of the -C<=over>/C<=back> block. - -=item * =item type mismatch (I<one> vs. I<two>) - -A list started with e.g. a bulletted C<=item> and continued with a -numbered one. This is obviously inconsistent. For most translators the -type of the I<first> C<=item> determines the type of the list. - -=item * I<N> unescaped C<E<lt>E<gt>> in paragraph - -Angle brackets not written as C<E<lt>ltE<gt>> and C<E<lt>gtE<gt>> -can potentially cause errors as they could be misinterpreted as -markup commands. This is only printed when the -warnings level is -greater than 1. - -=item * Unknown entity - -A character entity was found that does not belong to the standard -ISO set or the POD specials C<verbar> and C<sol>. - -=item * No items in =over - -The list opened with C<=over> does not contain any items. - -=item * No argument for =item - -C<=item> without any parameters is deprecated. It should either be followed -by C<*> to indicate an unordered list, by a number (optionally followed -by a dot) to indicate an ordered (numbered) list or simple text for a -definition list. - -=item * empty section in previous paragraph - -The previous section (introduced by a C<=head> command) does not contain -any text. This usually indicates that something is missing. Note: A -C<=head1> followed immediately by C<=head2> does not trigger this warning. - -=item * Verbatim paragraph in NAME section - -The NAME section (C<=head1 NAME>) should consist of a single paragraph -with the script/module name, followed by a dash `-' and a very short -description of what the thing is good for. - -=back - -=head2 Hyperlinks - -There are some warnings wrt. malformed hyperlinks. - -=over 4 - -=item * ignoring leading/trailing whitespace in link - -There is whitespace at the beginning or the end of the contents of -LE<lt>...E<gt>. - -=item * (section) in '$page' deprecated - -There is a section detected in the page name of LE<lt>...E<gt>, e.g. -C<LE<gt>passwd(2)E<gt>>. POD hyperlinks may point to POD documents only. -Please write C<CE<lt>passwd(2)E<gt>> instead. Some formatters are able -to expand this to appropriate code. For links to (builtin) functions, -please say C<LE<lt>perlfunc/mkdirE<gt>>, without (). - -=item * alternative text/node '%s' contains non-escaped | or / - -The characters C<|> and C</> are special in the LE<lt>...E<gt> context. -Although the hyperlink parser does its best to determine which "/" is -text and which is a delimiter in case of doubt, one ought to escape -these literal characters like this: - - / E<sol> - | E<verbar> - -=back - -=head1 RETURN VALUE - -B<podchecker> returns the number of POD syntax errors found or -1 if -there were no POD commands at all found in the file. - -=head1 EXAMPLES - -I<[T.B.D.]> - -=head1 INTERFACE - -While checking, this module collects document properties, e.g. the nodes -for hyperlinks (C<=headX>, C<=item>) and index entries (C<XE<lt>E<gt>>). -POD translators can use this feature to syntax-check and get the nodes in -a first pass before actually starting to convert. This is expensive in terms -of execution time, but allows for very robust conversions. - -=cut - -############################################################################# - -use strict; -#use diagnostics; -use Carp; -use Exporter; -use Pod::Parser; - -use vars qw(@ISA @EXPORT); -@ISA = qw(Pod::Parser); -@EXPORT = qw(&podchecker); - -use vars qw(%VALID_COMMANDS %VALID_SEQUENCES); - -my %VALID_COMMANDS = ( - 'pod' => 1, - 'cut' => 1, - 'head1' => 1, - 'head2' => 1, - 'over' => 1, - 'back' => 1, - 'item' => 1, - 'for' => 1, - 'begin' => 1, - 'end' => 1, -); - -my %VALID_SEQUENCES = ( - 'I' => 1, - 'B' => 1, - 'S' => 1, - 'C' => 1, - 'L' => 1, - 'F' => 1, - 'X' => 1, - 'Z' => 1, - 'E' => 1, -); - -# stolen from HTML::Entities -my %ENTITIES = ( - # Some normal chars that have special meaning in SGML context - amp => '&', # ampersand -'gt' => '>', # greater than -'lt' => '<', # less than - quot => '"', # double quote - - # PUBLIC ISO 8879-1986//ENTITIES Added Latin 1//EN//HTML - AElig => 'Æ', # capital AE diphthong (ligature) - Aacute => 'Á', # capital A, acute accent - Acirc => 'Â', # capital A, circumflex accent - Agrave => 'À', # capital A, grave accent - Aring => 'Å', # capital A, ring - Atilde => 'Ã', # capital A, tilde - Auml => 'Ä', # capital A, dieresis or umlaut mark - Ccedil => 'Ç', # capital C, cedilla - ETH => 'Ð', # capital Eth, Icelandic - Eacute => 'É', # capital E, acute accent - Ecirc => 'Ê', # capital E, circumflex accent - Egrave => 'È', # capital E, grave accent - Euml => 'Ë', # capital E, dieresis or umlaut mark - Iacute => 'Í', # capital I, acute accent - Icirc => 'Î', # capital I, circumflex accent - Igrave => 'Ì', # capital I, grave accent - Iuml => 'Ï', # capital I, dieresis or umlaut mark - Ntilde => 'Ñ', # capital N, tilde - Oacute => 'Ó', # capital O, acute accent - Ocirc => 'Ô', # capital O, circumflex accent - Ograve => 'Ò', # capital O, grave accent - Oslash => 'Ø', # capital O, slash - Otilde => 'Õ', # capital O, tilde - Ouml => 'Ö', # capital O, dieresis or umlaut mark - THORN => 'Þ', # capital THORN, Icelandic - Uacute => 'Ú', # capital U, acute accent - Ucirc => 'Û', # capital U, circumflex accent - Ugrave => 'Ù', # capital U, grave accent - Uuml => 'Ü', # capital U, dieresis or umlaut mark - Yacute => 'Ý', # capital Y, acute accent - aacute => 'á', # small a, acute accent - acirc => 'â', # small a, circumflex accent - aelig => 'æ', # small ae diphthong (ligature) - agrave => 'à', # small a, grave accent - aring => 'å', # small a, ring - atilde => 'ã', # small a, tilde - auml => 'ä', # small a, dieresis or umlaut mark - ccedil => 'ç', # small c, cedilla - eacute => 'é', # small e, acute accent - ecirc => 'ê', # small e, circumflex accent - egrave => 'è', # small e, grave accent - eth => 'ð', # small eth, Icelandic - euml => 'ë', # small e, dieresis or umlaut mark - iacute => 'í', # small i, acute accent - icirc => 'î', # small i, circumflex accent - igrave => 'ì', # small i, grave accent - iuml => 'ï', # small i, dieresis or umlaut mark - ntilde => 'ñ', # small n, tilde - oacute => 'ó', # small o, acute accent - ocirc => 'ô', # small o, circumflex accent - ograve => 'ò', # small o, grave accent - oslash => 'ø', # small o, slash - otilde => 'õ', # small o, tilde - ouml => 'ö', # small o, dieresis or umlaut mark - szlig => 'ß', # small sharp s, German (sz ligature) - thorn => 'þ', # small thorn, Icelandic - uacute => 'ú', # small u, acute accent - ucirc => 'û', # small u, circumflex accent - ugrave => 'ù', # small u, grave accent - uuml => 'ü', # small u, dieresis or umlaut mark - yacute => 'ý', # small y, acute accent - yuml => 'ÿ', # small y, dieresis or umlaut mark - - # Some extra Latin 1 chars that are listed in the HTML3.2 draft (21-May-96) - copy => '©', # copyright sign - reg => '®', # registered sign - nbsp => "\240", # non breaking space - - # Additional ISO-8859/1 entities listed in rfc1866 (section 14) - iexcl => '¡', - cent => '¢', - pound => '£', - curren => '¤', - yen => '¥', - brvbar => '¦', - sect => '§', - uml => '¨', - ordf => 'ª', - laquo => '«', -'not' => '¬', # not is a keyword in perl - shy => '', - macr => '¯', - deg => '°', - plusmn => '±', - sup1 => '¹', - sup2 => '²', - sup3 => '³', - acute => '´', - micro => 'µ', - para => '¶', - middot => '·', - cedil => '¸', - ordm => 'º', - raquo => '»', - frac14 => '¼', - frac12 => '½', - frac34 => '¾', - iquest => '¿', -'times' => '×', # times is a keyword in perl - divide => '÷', - -# some POD special entities - verbar => '|', - sol => '/' -); - -##--------------------------------------------------------------------------- - -##--------------------------------- -## Function definitions begin here -##--------------------------------- - -sub podchecker( $ ; $ % ) { - my ($infile, $outfile, %options) = @_; - local $_; - - ## Set defaults - $infile ||= \*STDIN; - $outfile ||= \*STDERR; - - ## Now create a pod checker - my $checker = new Pod::Checker(%options); - - ## Now check the pod document for errors - $checker->parse_from_file($infile, $outfile); - - ## Return the number of errors found - return $checker->num_errors(); -} - -##--------------------------------------------------------------------------- - -##------------------------------- -## Method definitions begin here -##------------------------------- - -################################## - -=over 4 - -=item C<Pod::Checker-E<gt>new( %options )> - -Return a reference to a new Pod::Checker object that inherits from -Pod::Parser and is used for calling the required methods later. The -following options are recognized: - -C<-warnings =E<gt> num> - Print warnings if C<num> is true. The higher the value of C<num>, -the more warnings are printed. Currently there are only levels 1 and 2. - -C<-quiet =E<gt> num> - If C<num> is true, do not print any errors/warnings. This is useful -when Pod::Checker is used to munge POD code into plain text from within -POD formatters. - -=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; - ## Initialize number of errors, and setup an error function to - ## increment this number and then print to the designated output. - $self->{_NUM_ERRORS} = 0; - $self->{-quiet} ||= 0; - # set the error handling subroutine - $self->errorsub($self->{-quiet} ? sub { 1; } : 'poderror'); - $self->{_commands} = 0; # total number of POD commands encountered - $self->{_list_stack} = []; # stack for nested lists - $self->{_have_begin} = ''; # stores =begin - $self->{_links} = []; # stack for internal hyperlinks - $self->{_nodes} = []; # stack for =head/=item nodes - $self->{_index} = []; # text in X<> - # print warnings? - $self->{-warnings} = 1 unless(defined $self->{-warnings}); - $self->{_current_head1} = ''; # the current =head1 block - $self->parseopts(-process_cut_cmd => 1, -warnings => $self->{-warnings}); -} - -################################## - -=item C<$checker-E<gt>poderror( @args )> - -=item C<$checker-E<gt>poderror( {%opts}, @args )> - -Internal method for printing errors and warnings. If no options are -given, simply prints "@_". The following options are recognized and used -to form the output: - - -msg - -A message to print prior to C<@args>. - - -line - -The line number the error occurred in. - - -file - -The file (name) the error occurred in. - - -severity - -The error level, should be 'WARNING' or 'ERROR'. - -=cut - -# Invoked as $self->poderror( @args ), or $self->poderror( {%opts}, @args ) -sub poderror { - my $self = shift; - my %opts = (ref $_[0]) ? %{shift()} : (); - - ## Retrieve options - chomp( my $msg = ($opts{-msg} || "")."@_" ); - my $line = (exists $opts{-line}) ? " at line $opts{-line}" : ""; - my $file = (exists $opts{-file}) ? " in file $opts{-file}" : ""; - unless (exists $opts{-severity}) { - ## See if can find severity in message prefix - $opts{-severity} = $1 if ( $msg =~ s/^\**\s*([A-Z]{3,}):\s+// ); - } - my $severity = (exists $opts{-severity}) ? "*** $opts{-severity}: " : ""; - - ## Increment error count and print message " - ++($self->{_NUM_ERRORS}) - if(!%opts || ($opts{-severity} && $opts{-severity} eq 'ERROR')); - my $out_fh = $self->output_handle() || \*STDERR; - print $out_fh ($severity, $msg, $line, $file, "\n") - if($self->{-warnings} || !%opts || $opts{-severity} ne 'WARNING'); -} - -################################## - -=item C<$checker-E<gt>num_errors()> - -Set (if argument specified) and retrieve the number of errors found. - -=cut - -sub num_errors { - return (@_ > 1) ? ($_[0]->{_NUM_ERRORS} = $_[1]) : $_[0]->{_NUM_ERRORS}; -} - -################################## - -=item C<$checker-E<gt>name()> - -Set (if argument specified) and retrieve the canonical name of POD as -found in the C<=head1 NAME> section. - -=cut - -sub name { - return (@_ > 1 && $_[1]) ? - ($_[0]->{-name} = $_[1]) : $_[0]->{-name}; -} - -################################## - -=item C<$checker-E<gt>node()> - -Add (if argument specified) and retrieve the nodes (as defined by C<=headX> -and C<=item>) of the current POD. The nodes are returned in the order of -their occurence. They consist of plain text, each piece of whitespace is -collapsed to a single blank. - -=cut - -sub node { - my ($self,$text) = @_; - if(defined $text) { - $text =~ s/\s+$//s; # strip trailing whitespace - $text =~ s/\s+/ /gs; # collapse whitespace - # add node, order important! - push(@{$self->{_nodes}}, $text); - # keep also a uniqueness counter - $self->{_unique_nodes}->{$text}++ if($text !~ /^\s*$/s); - return $text; - } - @{$self->{_nodes}}; -} - -################################## - -=item C<$checker-E<gt>idx()> - -Add (if argument specified) and retrieve the index entries (as defined by -C<XE<lt>E<gt>>) of the current POD. They consist of plain text, each piece -of whitespace is collapsed to a single blank. - -=cut - -# set/return index entries of current POD -sub idx { - my ($self,$text) = @_; - if(defined $text) { - $text =~ s/\s+$//s; # strip trailing whitespace - $text =~ s/\s+/ /gs; # collapse whitespace - # add node, order important! - push(@{$self->{_index}}, $text); - # keep also a uniqueness counter - $self->{_unique_nodes}->{$text}++ if($text !~ /^\s*$/s); - return $text; - } - @{$self->{_index}}; -} - -################################## - -=item C<$checker-E<gt>hyperlink()> - -Add (if argument specified) and retrieve the hyperlinks (as defined by -C<LE<lt>E<gt>>) of the current POD. They consist of an 2-item array: line -number and C<Pod::Hyperlink> object. - -=back - -=cut - -# set/return hyperlinks of the current POD -sub hyperlink { - my $self = shift; - if($_[0]) { - push(@{$self->{_links}}, $_[0]); - return $_[0]; - } - @{$self->{_links}}; -} - -## overrides for Pod::Parser - -sub end_pod { - ## Do some final checks and - ## print the number of errors found - my $self = shift; - my $infile = $self->input_file(); - my $out_fh = $self->output_handle(); - - if(@{$self->{_list_stack}}) { - # _TODO_ display, but don't count them for now - my $list; - while(($list = $self->_close_list('EOF',$infile)) && - $list->indent() ne 'auto') { - $self->poderror({ -line => 'EOF', -file => $infile, - -severity => 'ERROR', -msg => "=over on line " . - $list->start() . " without closing =back" }); #" - } - } - - # check validity of document internal hyperlinks - # first build the node names from the paragraph text - my %nodes; - foreach($self->node()) { - $nodes{$_} = 1; - if(/^(\S+)\s+\S/) { - # we have more than one word. Use the first as a node, too. - # This is used heavily in perlfunc.pod - $nodes{$1} ||= 2; # derived node - } - } - foreach($self->idx()) { - $nodes{$_} = 3; # index node - } - foreach($self->hyperlink()) { - my ($line,$link) = @$_; - # _TODO_ what if there is a link to the page itself by the name, - # e.g. in Tk::Pod : L<Tk::Pod/"DESCRIPTION"> - if($link->node() && !$link->page() && $link->type() ne 'hyperlink') { - my $node = $self->_check_ptree($self->parse_text($link->node(), - $line), $line, $infile, 'L'); - if($node && !$nodes{$node}) { - $self->poderror({ -line => $line || '', -file => $infile, - -severity => 'ERROR', - -msg => "unresolved internal link '$node'"}); - } - } - } - - # check the internal nodes for uniqueness. This pertains to - # =headX, =item and X<...> - foreach(grep($self->{_unique_nodes}->{$_} > 1, - keys %{$self->{_unique_nodes}})) { - $self->poderror({ -line => '-', -file => $infile, - -severity => 'WARNING', - -msg => "multiple occurence of link target '$_'"}); - } - - ## Print the number of errors found - my $num_errors = $self->num_errors(); - if ($num_errors > 0) { - printf $out_fh ("$infile has $num_errors pod syntax %s.\n", - ($num_errors == 1) ? "error" : "errors"); - } - elsif($self->{_commands} == 0) { - print $out_fh "$infile does not contain any pod commands.\n"; - $self->num_errors(-1); - } - else { - print $out_fh "$infile pod syntax OK.\n"; - } -} - -# check a POD command directive -sub command { - my ($self, $cmd, $paragraph, $line_num, $pod_para) = @_; - my ($file, $line) = $pod_para->file_line; - ## Check the command syntax - my $arg; # this will hold the command argument - if (! $VALID_COMMANDS{$cmd}) { - $self->poderror({ -line => $line, -file => $file, -severity => 'ERROR', - -msg => "Unknown command '$cmd'" }); - } - else { # found a valid command - $self->{_commands}++; # delete this line if below is enabled again - - ##### following check disabled due to strong request - #if(!$self->{_commands}++ && $cmd !~ /^head/) { - # $self->poderror({ -line => $line, -file => $file, - # -severity => 'WARNING', - # -msg => "file does not start with =head" }); - #} - - # check syntax of particular command - if($cmd eq 'over') { - # check for argument - $arg = $self->interpolate_and_check($paragraph, $line,$file); - my $indent = 4; # default - if($arg && $arg =~ /^\s*(\d+)\s*$/) { - $indent = $1; - } - # start a new list - $self->_open_list($indent,$line,$file); - } - elsif($cmd eq 'item') { - # are we in a list? - unless(@{$self->{_list_stack}}) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "=item without previous =over" }); - # auto-open in case we encounter many more - $self->_open_list('auto',$line,$file); - } - my $list = $self->{_list_stack}->[0]; - # check whether the previous item had some contents - if(defined $self->{_list_item_contents} && - $self->{_list_item_contents} == 0) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "previous =item has no contents" }); - } - if($list->{_has_par}) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "preceding non-item paragraph(s)" }); - delete $list->{_has_par}; - } - # check for argument - $arg = $self->interpolate_and_check($paragraph, $line, $file); - if($arg && $arg =~ /(\S+)/) { - $arg =~ s/[\s\n]+$//; - my $type; - if($arg =~ /^[*]\s*(\S*.*)/) { - $type = 'bullet'; - $self->{_list_item_contents} = $1 ? 1 : 0; - $arg = $1; - } - elsif($arg =~ /^\d+\.?\s*(\S*)/) { - $type = 'number'; - $self->{_list_item_contents} = $1 ? 1 : 0; - $arg = $1; - } - else { - $type = 'definition'; - $self->{_list_item_contents} = 1; - } - my $first = $list->type(); - if($first && $first ne $type) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "=item type mismatch ('$first' vs. '$type')"}); - } - else { # first item - $list->type($type); - } - } - else { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "No argument for =item" }); - $arg = ' '; # empty - $self->{_list_item_contents} = 0; - } - # add this item - $list->item($arg); - # remember this node - $self->node($arg); - } - elsif($cmd eq 'back') { - # check if we have an open list - unless(@{$self->{_list_stack}}) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "=back without previous =over" }); - } - else { - # check for spurious characters - $arg = $self->interpolate_and_check($paragraph, $line,$file); - if($arg && $arg =~ /\S/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Spurious character(s) after =back" }); - } - # close list - my $list = $self->_close_list($line,$file); - # check for empty lists - if(!$list->item() && $self->{-warnings}) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "No items in =over (at line " . - $list->start() . ") / =back list"}); #" - } - } - } - elsif($cmd =~ /^head(\d+)/) { - # check whether the previous =head section had some contents - if(defined $self->{_commands_in_head} && - $self->{_commands_in_head} == 0 && - defined $self->{_last_head} && - $self->{_last_head} >= $1) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "empty section in previous paragraph"}); - } - $self->{_commands_in_head} = -1; - $self->{_last_head} = $1; - # check if there is an open list - if(@{$self->{_list_stack}}) { - my $list; - while(($list = $self->_close_list($line,$file)) && - $list->indent() ne 'auto') { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "=over on line ". $list->start() . - " without closing =back (at $cmd)" }); - } - } - # remember this node - $arg = $self->interpolate_and_check($paragraph, $line,$file); - $arg =~ s/[\s\n]+$//s; - $self->node($arg); - unless(length($arg)) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "empty =$cmd"}); - } - if($cmd eq 'head1') { - $self->{_current_head1} = $arg; - } else { - $self->{_current_head1} = ''; - } - } - elsif($cmd eq 'begin') { - if($self->{_have_begin}) { - # already have a begin - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Nested =begin's (first at line " . - $self->{_have_begin} . ")"}); - } - else { - # check for argument - $arg = $self->interpolate_and_check($paragraph, $line,$file); - unless($arg && $arg =~ /(\S+)/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "No argument for =begin"}); - } - # remember the =begin - $self->{_have_begin} = "$line:$1"; - } - } - elsif($cmd eq 'end') { - if($self->{_have_begin}) { - # close the existing =begin - $self->{_have_begin} = ''; - # check for spurious characters - $arg = $self->interpolate_and_check($paragraph, $line,$file); - # the closing argument is optional - #if($arg && $arg =~ /\S/) { - # $self->poderror({ -line => $line, -file => $file, - # -severity => 'WARNING', - # -msg => "Spurious character(s) after =end" }); - #} - } - else { - # don't have a matching =begin - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "=end without =begin" }); - } - } - elsif($cmd eq 'for') { - unless($paragraph =~ /\s*(\S+)\s*/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "=for without formatter specification" }); - } - $arg = ''; # do not expand paragraph below - } - elsif($cmd =~ /^(pod|cut)$/) { - # check for argument - $arg = $self->interpolate_and_check($paragraph, $line,$file); - if($arg && $arg =~ /(\S+)/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Spurious text after =$cmd"}); - } - } - $self->{_commands_in_head}++; - ## Check the interior sequences in the command-text - $self->interpolate_and_check($paragraph, $line,$file) - unless(defined $arg); - } -} - -sub _open_list -{ - my ($self,$indent,$line,$file) = @_; - my $list = Pod::List->new( - -indent => $indent, - -start => $line, - -file => $file); - unshift(@{$self->{_list_stack}}, $list); - undef $self->{_list_item_contents}; - $list; -} - -sub _close_list -{ - my ($self,$line,$file) = @_; - my $list = shift(@{$self->{_list_stack}}); - if(defined $self->{_list_item_contents} && - $self->{_list_item_contents} == 0) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "previous =item has no contents" }); - } - undef $self->{_list_item_contents}; - $list; -} - -# process a block of some text -sub interpolate_and_check { - my ($self, $paragraph, $line, $file) = @_; - ## Check the interior sequences in the command-text - # and return the text - $self->_check_ptree( - $self->parse_text($paragraph,$line), $line, $file, ''); -} - -sub _check_ptree { - my ($self,$ptree,$line,$file,$nestlist) = @_; - local($_); - my $text = ''; - # process each node in the parse tree - foreach(@$ptree) { - # regular text chunk - unless(ref) { - my $count; - # count the unescaped angle brackets - # complain only when warning level is greater than 1 - my $i = $_; - if($count = $i =~ tr/<>/<>/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "$count unescaped <> in paragraph" }) - if($self->{-warnings} && $self->{-warnings}>1); - } - $text .= $i; - next; - } - # have an interior sequence - my $cmd = $_->cmd_name(); - my $contents = $_->parse_tree(); - ($file,$line) = $_->file_line(); - # check for valid tag - if (! $VALID_SEQUENCES{$cmd}) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => qq(Unknown interior-sequence '$cmd')}); - # expand it anyway - $text .= $self->_check_ptree($contents, $line, $file, "$nestlist$cmd"); - next; - } - if($nestlist =~ /$cmd/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "nested commands $cmd<...$cmd<...>...>"}); - # _TODO_ should we add the contents anyway? - # expand it anyway, see below - } - if($cmd eq 'E') { - # preserve entities - if(@$contents > 1 || ref $$contents[0] || $$contents[0] !~ /^\w+$/) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "garbled entity " . $_->raw_text()}); - next; - } - my $ent = $$contents[0]; - my $val; - if($ent =~ /^0x[0-9a-f]+$/i) { - # hexadec entity - $val = hex($ent); - } - elsif($ent =~ /^0\d+$/) { - # octal - $val = oct($ent); - } - elsif($ent =~ /^\d+$/) { - # numeric entity - $val = $ent; - } - if(defined $val) { - if($val>0 && $val<256) { - $text .= chr($val); - } - else { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Entity number out of range " . $_->raw_text()}); - } - } - elsif($ENTITIES{$ent}) { - # known ISO entity - $text .= $ENTITIES{$ent}; - } - else { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => "Unknown entity " . $_->raw_text()}); - $text .= "E<$ent>"; - } - } - elsif($cmd eq 'L') { - # try to parse the hyperlink - my $link = Pod::Hyperlink->new($contents->raw_text()); - unless(defined $link) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "malformed link " . $_->raw_text() ." : $@"}); - next; - } - $link->line($line); # remember line - if($self->{-warnings}) { - foreach my $w ($link->warning()) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => $w }); - } - } - # check the link text - $text .= $self->_check_ptree($self->parse_text($link->text(), - $line), $line, $file, "$nestlist$cmd"); - # remember link - $self->hyperlink([$line,$link]); - } - elsif($cmd =~ /[BCFIS]/) { - # add the guts - $text .= $self->_check_ptree($contents, $line, $file, "$nestlist$cmd"); - } - elsif($cmd eq 'Z') { - if(length($contents->raw_text())) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Nonempty Z<>"}); - } - } - elsif($cmd eq 'X') { - my $idx = $self->_check_ptree($contents, $line, $file, "$nestlist$cmd"); - if($idx =~ /^\s*$/s) { - $self->poderror({ -line => $line, -file => $file, - -severity => 'ERROR', - -msg => "Empty X<>"}); - } - else { - # remember this node - $self->idx($idx); - } - } - else { - # not reached - die "internal error"; - } - } - $text; -} - -# process a block of verbatim text -sub verbatim { - ## Nothing particular to check - my ($self, $paragraph, $line_num, $pod_para) = @_; - - $self->_preproc_par($paragraph); - - if($self->{_current_head1} eq 'NAME') { - my ($file, $line) = $pod_para->file_line; - $self->poderror({ -line => $line, -file => $file, - -severity => 'WARNING', - -msg => 'Verbatim paragraph in NAME section' }); - } -} - -# process a block of regular text -sub textblock { - my ($self, $paragraph, $line_num, $pod_para) = @_; - my ($file, $line) = $pod_para->file_line; - - $self->_preproc_par($paragraph); - - # skip this paragraph if in a =begin block - unless($self->{_have_begin}) { - my $block = $self->interpolate_and_check($paragraph, $line,$file); - if($self->{_current_head1} eq 'NAME') { - if($block =~ /^\s*(\S+?)\s*[,-]/) { - # this is the canonical name - $self->{-name} = $1 unless(defined $self->{-name}); - } - } - } -} - -sub _preproc_par -{ - my $self = shift; - $_[0] =~ s/[\s\n]+$//; - if($_[0]) { - $self->{_commands_in_head}++; - $self->{_list_item_contents}++ if(defined $self->{_list_item_contents}); - if(@{$self->{_list_stack}} && !$self->{_list_stack}->[0]->item()) { - $self->{_list_stack}->[0]->{_has_par} = 1; - } - } -} - -1; - -__END__ - -=head1 AUTHOR - -Brad Appleton E<lt>bradapp@enteract.comE<gt> (initial version), -Marek Rouchal E<lt>marek@saftsack.fs.uni-bayreuth.deE<gt> - -Based on code for B<Pod::Text::pod2text()> written by -Tom Christiansen E<lt>tchrist@mox.perl.comE<gt> - -=cut - diff --git a/contrib/perl5/lib/Pod/Find.pm b/contrib/perl5/lib/Pod/Find.pm deleted file mode 100644 index 4a0ecb9..0000000 --- a/contrib/perl5/lib/Pod/Find.pm +++ /dev/null @@ -1,445 +0,0 @@ -############################################################################# -# Pod/Find.pm -- finds files containing POD documentation -# -# Author: Marek Rouchal <marek@saftsack.fs.uni-bayreuth.de> -# -# 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 vars qw($VERSION); -$VERSION = 0.21; ## Current version of this package -require 5.005; ## requires this Perl version or later -use Carp; - -############################################################################# - -=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<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); - -=cut - -use strict; -#use diagnostics; -use Exporter; -use File::Spec; -use File::Find; -use 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 prepended to 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}); - $opts{-perl} = 1; - } - - if($opts{-inc}) { - push(@search, grep($_ ne '.',@INC)); - $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) - $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 - $try = File::Spec->canonpath($try) if ($^O ne 'VMS'); - 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 = qq!^\Q$try\E/!; - File::Find::find( sub { - my $item = $File::Find::name; - if(-d) { - if($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; - %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; - } - $$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 =~ /\.(pod|pm|plx?)\z/i || -x _ )) { - return undef; - } - - return undef 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!!s; - $name =~ s!$SIMPLIFY_RX!!os if(defined $SIMPLIFY_RX); - } - else { - $name =~ s:^.*/::s; - } - _simplify($name); - $name =~ s!/+!::!g; #/ - $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 - $str =~ s:^.*/::s; - _simplify($str); - $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 occurence 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' => [ '.' ], - ); - - # 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 - push (@search_dirs, @INC) if $options{'-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'}; - } - - # Loop over directories - Dir: foreach my $dir ( @search_dirs ) { - - # Don't bother if cant 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); - 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; - } - if(-d File::Spec->catdir($dir,'pod')) { - $dir = File::Spec->catdir($dir,'pod'); - redo Dir; - } - } - # No match; - return undef; -} - -=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 - unless(open(POD,"<$file")) { - warn "Error: $file is unreadable: $!\n"; - return undef; - } - - local $/ = undef; - my $pod = <POD>; - close(POD) || die "Error closing $file: $!\n"; - unless($pod =~ /\n=(head\d|pod|over|item)\b/s) { - warn "No POD in $file, skipping.\n" - if($verbose); - return 0; - } - - return 1; -} - -=head1 AUTHOR - -Marek Rouchal E<lt>marek@saftsack.fs.uni-bayreuth.deE<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>. - -=head1 SEE ALSO - -L<Pod::Parser>, L<Pod::Checker>, L<perldoc> - -=cut - -1; - diff --git a/contrib/perl5/lib/Pod/Functions.pm b/contrib/perl5/lib/Pod/Functions.pm deleted file mode 100644 index 44619d5..0000000 --- a/contrib/perl5/lib/Pod/Functions.pm +++ /dev/null @@ -1,302 +0,0 @@ -package Pod::Functions; - -#:vi:set ts=20 - -require Exporter; - -@ISA = qw(Exporter); -@EXPORT = qw(%Kinds %Type %Flavor %Type_Description @Type_Order); - -%Type_Description = ( - 'ARRAY' => 'Functions for real @ARRAYs', - 'Binary' => 'Functions for fixed length data or records', - 'File' => 'Functions for filehandles, files, or directories', - 'Flow' => 'Keywords related to control flow of your perl program', - 'HASH' => 'Functions for real %HASHes', - 'I/O' => 'Input and output functions', - 'LIST' => 'Functions for list data', - 'Math' => 'Numeric functions', - 'Misc' => 'Miscellaneous functions', - 'Modules' => 'Keywords related to perl modules', - 'Network' => 'Fetching network info', - 'Objects' => 'Keywords related to classes and object-orientedness', - 'Process' => 'Functions for processes and process groups', - 'Regexp' => 'Regular expressions and pattern matching', - 'Socket' => 'Low-level socket functions', - 'String' => 'Functions for SCALARs or strings', - 'SysV' => 'System V interprocess communication functions', - 'Time' => 'Time-related functions', - 'User' => 'Fetching user and group info', - 'Namespace' => 'Keywords altering or affecting scoping of identifiers', -); - -@Type_Order = qw{ - String - Regexp - Math - ARRAY - LIST - HASH - I/O - Binary - File - Flow - Namespace - Misc - Process - Modules - Objects - Socket - SysV - User - Network - Time -}; - -while (<DATA>) { - chomp; - s/#.*//; - next unless $_; - ($name, $type, $text) = split " ", $_, 3; - $Type{$name} = $type; - $Flavor{$name} = $text; - for $type ( split /[,\s]+/, $type ) { - push @{$Kinds{$type}}, $name; - } -} - -close DATA; - -unless (caller) { - foreach $type ( @Type_Order ) { - $list = join(", ", sort @{$Kinds{$type}}); - $typedesc = $Type_Description{$type} . ":"; - write; - } -} - -format = - -^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - $typedesc -~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - $typedesc - ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - $list -. - -1 - -__DATA__ --X File a file test (-r, -x, etc) -abs Math absolute value function -accept Socket accept an incoming socket connect -alarm Process schedule a SIGALRM -atan2 Math arctangent of Y/X in the range -PI to PI -bind Socket binds an address to a socket -binmode I/O prepare binary files for I/O -bless Objects create an object -caller Flow,Namespace get context of the current subroutine call -chdir File change your current working directory -chmod File changes the permissions on a list of files -chomp String remove a trailing record separator from a string -chop String remove the last character from a string -chown File change the owership on a list of files -chr String get character this number represents -chroot File make directory new root for path lookups -close I/O close file (or pipe or socket) handle -closedir I/O close directory handle -connect Socket connect to a remote socket -continue Flow optional trailing block in a while or foreach -cos Math cosine function -crypt String one-way passwd-style encryption -dbmclose Objects,I/O breaks binding on a tied dbm file -dbmopen Objects,I/O create binding on a tied dbm file -defined Misc test whether a value, variable, or function is defined -delete HASH deletes a value from a hash -die I/O,Flow raise an exception or bail out -do Flow,Modules turn a BLOCK into a TERM -dump Misc,Flow create an immediate core dump -each HASH retrieve the next key/value pair from a hash -endgrent User be done using group file -endhostent User be done using hosts file -endnetent User be done using networks file -endprotoent Network be done using protocols file -endpwent User be done using passwd file -endservent Network be done using services file -eof I/O test a filehandle for its end -eval Flow,Misc catch exceptions or compile and run code -exec Process abandon this program to run another -exists HASH test whether a hash key is present -exit Flow terminate this program -exp Math raise I<e> to a power -fcntl File file control system call -fileno I/O return file descriptor from filehandle -flock I/O lock an entire file with an advisory lock -fork Process create a new process just like this one -format I/O declare a picture format with use by the write() function -formline Misc internal function used for formats -getc I/O get the next character from the filehandle -getgrent User get next group record -getgrgid User get group record given group user ID -getgrnam User get group record given group name -gethostbyaddr Network get host record given its address -gethostbyname Network get host record given name -gethostent Network get next hosts record -getlogin User return who logged in at this tty -getnetbyaddr Network get network record given its address -getnetbyname Network get networks record given name -getnetent Network get next networks record -getpeername Socket find the other end of a socket connection -getpgrp Process get process group -getppid Process get parent process ID -getpriority Process get current nice value -getprotobyname Network get protocol record given name -getprotobynumber Network get protocol record numeric protocol -getprotoent Network get next protocols record -getpwent User get next passwd record -getpwnam User get passwd record given user login name -getpwuid User get passwd record given user ID -getservbyname Network get services record given its name -getservbyport Network get services record given numeric port -getservent Network get next services record -getsockname Socket retrieve the sockaddr for a given socket -getsockopt Socket get socket options on a given socket -glob File expand filenames using wildcards -gmtime Time convert UNIX time into record or string using Greenwich time -goto Flow create spaghetti code -grep LIST locate elements in a list test true against a given criterion -hex Math,String convert a string to a hexadecimal number -import Modules,Namespace patch a module's namespace into your own -index String find a substring within a string -int Math get the integer portion of a number -ioctl File system-dependent device control system call -join LIST join a list into a string using a separator -keys HASH retrieve list of indices from a hash -kill Process send a signal to a process or process group -last Flow exit a block prematurely -lc String return lower-case version of a string -lcfirst String return a string with just the next letter in lower case -length String return the number of bytes in a string -link File create a hard link in the filesytem -listen Socket register your socket as a server -local Misc,Namespace create a temporary value for a global variable (dynamic scoping) -localtime Time convert UNIX time into record or string using local time -lock Threads get a thread lock on a variable, subroutine, or method -log Math retrieve the natural logarithm for a number -lstat File stat a symbolic link -m// Regexp match a string with a regular expression pattern -map LIST apply a change to a list to get back a new list with the changes -mkdir File create a directory -msgctl SysV SysV IPC message control operations -msgget SysV get SysV IPC message queue -msgrcv SysV receive a SysV IPC message from a message queue -msgsnd SysV send a SysV IPC message to a message queue -my Misc,Namespace declare and assign a local variable (lexical scoping) -next Flow iterate a block prematurely -no Modules unimport some module symbols or semantics at compile time -package Modules,Objects,Namespace declare a separate global namespace -prototype Flow,Misc get the prototype (if any) of a subroutine -oct String,Math convert a string to an octal number -open File open a file, pipe, or descriptor -opendir File open a directory -ord String find a character's numeric representation -pack Binary,String convert a list into a binary representation -pipe Process open a pair of connected filehandles -pop ARRAY remove the last element from an array and return it -pos Regexp find or set the offset for the last/next m//g search -print I/O output a list to a filehandle -printf I/O output a formatted list to a filehandle -push ARRAY append one or more elements to an array -q/STRING/ String singly quote a string -qq/STRING/ String doubly quote a string -quotemeta Regexp quote regular expression magic characters -qw/STRING/ LIST quote a list of words -qx/STRING/ Process backquote quote a string -qr/PATTERN/ Regexp Compile pattern -rand Math retrieve the next pseudorandom number -read I/O,Binary fixed-length buffered input from a filehandle -readdir I/O get a directory from a directory handle -readline I/O fetch a record from a file -readlink File determine where a symbolic link is pointing -recv Socket receive a message over a Socket -redo Flow start this loop iteration over again -ref Objects find out the type of thing being referenced -rename File change a filename -require Modules load in external functions from a library at runtime -reset Misc clear all variables of a given name -return Flow get out of a function early -reverse String,LIST flip a string or a list -rewinddir I/O reset directory handle -rindex String right-to-left substring search -rmdir File remove a directory -s/// Regexp replace a pattern with a string -scalar Misc force a scalar context -seek I/O reposition file pointer for random-access I/O -seekdir I/O reposition directory pointer -select I/O reset default output or do I/O multiplexing -semctl SysV SysV semaphore control operations -semget SysV get set of SysV semaphores -semop SysV SysV semaphore operations -send Socket send a message over a socket -setgrent User prepare group file for use -sethostent Network prepare hosts file for use -setnetent Network prepare networks file for use -setpgrp Process set the process group of a process -setpriority Process set a process's nice value -setprotoent Network prepare protocols file for use -setpwent User prepare passwd file for use -setservent Network prepare services file for use -setsockopt Socket set some socket options -shift ARRAY remove the first element of an array, and return it -shmctl SysV SysV shared memory operations -shmget SysV get SysV shared memory segment identifier -shmread SysV read SysV shared memory -shmwrite SysV write SysV shared memory -shutdown Socket close down just half of a socket connection -sin Math return the sine of a number -sleep Process block for some number of seconds -socket Socket create a socket -socketpair Socket create a pair of sockets -sort LIST sort a list of values -splice ARRAY add or remove elements anywhere in an array -split Regexp split up a string using a regexp delimiter -sprintf String formatted print into a string -sqrt Math square root function -srand Math seed the random number generator -stat File get a file's status information -study Regexp optimize input data for repeated searches -sub Flow declare a subroutine, possibly anonymously -substr String get or alter a portion of a stirng -symlink File create a symbolic link to a file -syscall I/O,Binary execute an arbitrary system call -sysread I/O,Binary fixed-length unbuffered input from a filehandle -sysseek I/O,Binary position I/O pointer on handle used with sysread and syswrite -system Process run a separate program -syswrite I/O,Binary fixed-length unbuffered output to a filehandle -tell I/O get current seekpointer on a filehandle -telldir I/O get current seekpointer on a directory handle -tie Objects bind a variable to an object class -time Time return number of seconds since 1970 -times Process,Time return elapsed time for self and child processes -tr/// String transliterate a string -truncate I/O shorten a file -uc String return upper-case version of a string -ucfirst String return a string with just the next letter in upper case -umask File set file creation mode mask -undef Misc remove a variable or function definition -unlink File remove one link to a file -unpack Binary,LIST convert binary structure into normal perl variables -unshift ARRAY prepend more elements to the beginning of a list -untie Objects break a tie binding to a variable -use Modules,Namespace load a module and import its namespace -use Objects load in a module at compile time -utime File set a file's last access and modify times -values HASH return a list of the values in a hash -vec Binary test or set particular bits in a string -wait Process wait for any child process to die -waitpid Process wait for a particular child process to die -wantarray Misc,Flow get void vs scalar vs list context of current subroutine call -warn I/O print debugging info -write I/O print a picture record -y/// String transliterate a string diff --git a/contrib/perl5/lib/Pod/Html.pm b/contrib/perl5/lib/Pod/Html.pm deleted file mode 100644 index f70a42b..0000000 --- a/contrib/perl5/lib/Pod/Html.pm +++ /dev/null @@ -1,2025 +0,0 @@ -package Pod::Html; -use strict; -require Exporter; - -use vars qw($VERSION @ISA @EXPORT); -$VERSION = 1.03; -@ISA = qw(Exporter); -@EXPORT = qw(pod2html htmlify); - -use Carp; -use Config; -use Cwd; -use File::Spec::Unix; -use Getopt::Long; -use Pod::Functions; - -use locale; # make \w work right in non-ASCII lands - -=head1 NAME - -Pod::Html - module to convert pod files to HTML - -=head1 SYNOPSIS - - use Pod::Html; - pod2html([options]); - -=head1 DESCRIPTION - -Converts files from pod format (see L<perlpod>) to HTML format. It -can automatically generate indexes and cross-references, and it keeps -a cache of things it knows how to cross-reference. - -=head1 ARGUMENTS - -Pod::Html takes the following arguments: - -=over 4 - -=item backlink - - --backlink="Back to Top" - -Adds "Back to Top" links in front of every HEAD1 heading (except for -the first). By default, no backlink are being generated. - -=item css - - --css=stylesheet - -Specify the URL of a cascading style sheet. - -=item flush - - --flush - -Flushes the item and directory caches. - -=item header - - --header - --noheader - -Creates header and footer blocks containing the text of the NAME -section. By default, no headers are being generated. - -=item help - - --help - -Displays the usage message. - -=item htmldir - - --htmldir=name - -Sets the directory in which the resulting HTML file is placed. This -is used to generate relative links to other files. Not passing this -causes all links to be absolute, since this is the value that tells -Pod::Html the root of the documentation tree. - -=item htmlroot - - --htmlroot=name - -Sets the base URL for the HTML files. When cross-references are made, -the HTML root is prepended to the URL. - -=item index - - --index - --noindex - -Generate an index at the top of the HTML file. This is the default -behaviour. - -=item infile - - --infile=name - -Specify the pod file to convert. Input is taken from STDIN if no -infile is specified. - -=item libpods - - --libpods=name:...:name - -List of page names (eg, "perlfunc") which contain linkable C<=item>s. - -=item netscape - - --netscape - --nonetscape - -Use Netscape HTML directives when applicable. By default, they will -B<not> be used. - -=item outfile - - --outfile=name - -Specify the HTML file to create. Output goes to STDOUT if no outfile -is specified. - -=item podpath - - --podpath=name:...:name - -Specify which subdirectories of the podroot contain pod files whose -HTML converted forms can be linked-to in cross-references. - -=item podroot - - --podroot=name - -Specify the base directory for finding library pods. - -=item quiet - - --quiet - --noquiet - -Don't display I<mostly harmless> warning messages. These messages -will be displayed by default. But this is not the same as C<verbose> -mode. - -=item recurse - - --recurse - --norecurse - -Recurse into subdirectories specified in podpath (default behaviour). - -=item title - - --title=title - -Specify the title of the resulting HTML file. - -=item verbose - - --verbose - --noverbose - -Display progress messages. By default, they won't be displayed. - -=back - -=head1 EXAMPLE - - pod2html("pod2html", - "--podpath=lib:ext:pod:vms", - "--podroot=/usr/src/perl", - "--htmlroot=/perl/nmanual", - "--libpods=perlfunc:perlguts:perlvar:perlrun:perlop", - "--recurse", - "--infile=foo.pod", - "--outfile=/perl/nmanual/foo.html"); - -=head1 ENVIRONMENT - -Uses $Config{pod2html} to setup default options. - -=head1 AUTHOR - -Tom Christiansen, E<lt>tchrist@perl.comE<gt>. - -=head1 SEE ALSO - -L<perlpod> - -=head1 COPYRIGHT - -This program is distributed under the Artistic License. - -=cut - -my $cache_ext = $^O eq 'VMS' ? ".tmp" : ".x~~"; -my $dircache = "pod2htmd$cache_ext"; -my $itemcache = "pod2htmi$cache_ext"; - -my @begin_stack = (); # begin/end stack - -my @libpods = (); # files to search for links from C<> directives -my $htmlroot = "/"; # http-server base directory from which all - # relative paths in $podpath stem. -my $htmldir = ""; # The directory to which the html pages - # will (eventually) be written. -my $htmlfile = ""; # write to stdout by default -my $htmlfileurl = "" ; # The url that other files would use to - # refer to this file. This is only used - # to make relative urls that point to - # other files. -my $podfile = ""; # read from stdin by default -my @podpath = (); # list of directories containing library pods. -my $podroot = "."; # filesystem base directory from which all - # relative paths in $podpath stem. -my $css = ''; # Cascading style sheet -my $recurse = 1; # recurse on subdirectories in $podpath. -my $quiet = 0; # not quiet by default -my $verbose = 0; # not verbose by default -my $doindex = 1; # non-zero if we should generate an index -my $backlink = ''; # text for "back to top" links -my $listlevel = 0; # current list depth -my @listend = (); # the text to use to end the list. -my $after_lpar = 0; # set to true after a par in an =item -my $ignore = 1; # whether or not to format text. we don't - # format text until we hit our first pod - # directive. - -my %items_named = (); # for the multiples of the same item in perlfunc -my @items_seen = (); -my $netscape = 0; # whether or not to use netscape directives. -my $title; # title to give the pod(s) -my $header = 0; # produce block header/footer -my $top = 1; # true if we are at the top of the doc. used - # to prevent the first <HR> directive. -my $paragraph; # which paragraph we're processing (used - # for error messages) -my $ptQuote = 0; # status of double-quote conversion -my %pages = (); # associative array used to find the location - # of pages referenced by L<> links. -my %sections = (); # sections within this page -my %items = (); # associative array used to find the location - # of =item directives referenced by C<> links -my %local_items = (); # local items - avoid destruction of %items -my $Is83; # is dos with short filenames (8.3) - -sub init_globals { -$dircache = "pod2htmd$cache_ext"; -$itemcache = "pod2htmi$cache_ext"; - -@begin_stack = (); # begin/end stack - -@libpods = (); # files to search for links from C<> directives -$htmlroot = "/"; # http-server base directory from which all - # relative paths in $podpath stem. -$htmldir = ""; # The directory to which the html pages - # will (eventually) be written. -$htmlfile = ""; # write to stdout by default -$podfile = ""; # read from stdin by default -@podpath = (); # list of directories containing library pods. -$podroot = "."; # filesystem base directory from which all - # relative paths in $podpath stem. -$css = ''; # Cascading style sheet -$recurse = 1; # recurse on subdirectories in $podpath. -$quiet = 0; # not quiet by default -$verbose = 0; # not verbose by default -$doindex = 1; # non-zero if we should generate an index -$backlink = ''; # text for "back to top" links -$listlevel = 0; # current list depth -@listend = (); # the text to use to end the list. -$after_lpar = 0; # set to true after a par in an =item -$ignore = 1; # whether or not to format text. we don't - # format text until we hit our first pod - # directive. - -@items_seen = (); -%items_named = (); -$netscape = 0; # whether or not to use netscape directives. -$header = 0; # produce block header/footer -$title = ''; # title to give the pod(s) -$top = 1; # true if we are at the top of the doc. used - # to prevent the first <HR> directive. -$paragraph = ''; # which paragraph we're processing (used - # for error messages) -%sections = (); # sections within this page - -# These are not reinitialised here but are kept as a cache. -# See get_cache and related cache management code. -#%pages = (); # associative array used to find the location - # of pages referenced by L<> links. -#%items = (); # associative array used to find the location - # of =item directives referenced by C<> links -%local_items = (); -$Is83=$^O eq 'dos'; -} - -# -# clean_data: global clean-up of pod data -# -sub clean_data($){ - my( $dataref ) = @_; - my $i; - for( $i = 0; $i <= $#$dataref; $i++ ){ - ${$dataref}[$i] =~ s/\s+\Z//; - - # have a look for all-space lines - if( ${$dataref}[$i] =~ /^\s+$/m ){ - my @chunks = split( /^\s+$/m, ${$dataref}[$i] ); - splice( @$dataref, $i, 1, @chunks ); - } - } -} - - -sub pod2html { - local(@ARGV) = @_; - local($/); - local $_; - - init_globals(); - - $Is83 = 0 if (defined (&Dos::UseLFN) && Dos::UseLFN()); - - # cache of %pages and %items from last time we ran pod2html - - #undef $opt_help if defined $opt_help; - - # parse the command-line parameters - parse_command_line(); - - # set some variables to their default values if necessary - local *POD; - unless (@ARGV && $ARGV[0]) { - $podfile = "-" unless $podfile; # stdin - open(POD, "<$podfile") - || die "$0: cannot open $podfile file for input: $!\n"; - } else { - $podfile = $ARGV[0]; # XXX: might be more filenames - *POD = *ARGV; - } - $htmlfile = "-" unless $htmlfile; # stdout - $htmlroot = "" if $htmlroot eq "/"; # so we don't get a // - $htmldir =~ s#/\z## ; # so we don't get a // - if ( $htmlroot eq '' - && defined( $htmldir ) - && $htmldir ne '' - && substr( $htmlfile, 0, length( $htmldir ) ) eq $htmldir - ) - { - # Set the 'base' url for this file, so that we can use it - # as the location from which to calculate relative links - # to other files. If this is '', then absolute links will - # be used throughout. - $htmlfileurl= "$htmldir/" . substr( $htmlfile, length( $htmldir ) + 1); - } - - # read the pod a paragraph at a time - warn "Scanning for sections in input file(s)\n" if $verbose; - $/ = ""; - my @poddata = <POD>; - close(POD); - clean_data( \@poddata ); - - # scan the pod for =head[1-6] directives and build an index - my $index = scan_headings(\%sections, @poddata); - - unless($index) { - warn "No headings in $podfile\n" if $verbose; - } - - # open the output file - open(HTML, ">$htmlfile") - || die "$0: cannot open $htmlfile file for output: $!\n"; - - # put a title in the HTML file if one wasn't specified - if ($title eq '') { - TITLE_SEARCH: { - for (my $i = 0; $i < @poddata; $i++) { - if ($poddata[$i] =~ /^=head1\s*NAME\b/m) { - for my $para ( @poddata[$i, $i+1] ) { - last TITLE_SEARCH - if ($title) = $para =~ /(\S+\s+-+.*\S)/s; - } - } - - } - } - } - if (!$title and $podfile =~ /\.pod\z/) { - # probably a split pod so take first =head[12] as title - for (my $i = 0; $i < @poddata; $i++) { - last if ($title) = $poddata[$i] =~ /^=head[12]\s*(.*)/; - } - warn "adopted '$title' as title for $podfile\n" - if $verbose and $title; - } - if ($title) { - $title =~ s/\s*\(.*\)//; - } else { - warn "$0: no title for $podfile" unless $quiet; - $podfile =~ /^(.*)(\.[^.\/]+)?\z/s; - $title = ($podfile eq "-" ? 'No Title' : $1); - warn "using $title" if $verbose; - } - my $csslink = $css ? qq(\n<LINK REL="stylesheet" HREF="$css" TYPE="text/css">) : ''; - $csslink =~ s,\\,/,g; - $csslink =~ s,(/.):,$1|,; - - my $block = $header ? <<END_OF_BLOCK : ''; -<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH=100%> -<TR><TD CLASS=block VALIGN=MIDDLE WIDTH=100% BGCOLOR="#cccccc"> -<FONT SIZE=+1><STRONG><P CLASS=block> $title</P></STRONG></FONT> -</TD></TR> -</TABLE> -END_OF_BLOCK - - print HTML <<END_OF_HEAD; -<HTML> -<HEAD> -<TITLE>$title</TITLE>$csslink -<LINK REV="made" HREF="mailto:$Config{perladmin}"> -</HEAD> - -<BODY> -$block -END_OF_HEAD - - # load/reload/validate/cache %pages and %items - get_cache($dircache, $itemcache, \@podpath, $podroot, $recurse); - - # scan the pod for =item directives - scan_items( \%local_items, "", @poddata); - - # put an index at the top of the file. note, if $doindex is 0 we - # still generate an index, but surround it with an html comment. - # that way some other program can extract it if desired. - $index =~ s/--+/-/g; - print HTML "<A NAME=\"__index__\"></A>\n"; - print HTML "<!-- INDEX BEGIN -->\n"; - print HTML "<!--\n" unless $doindex; - print HTML $index; - print HTML "-->\n" unless $doindex; - print HTML "<!-- INDEX END -->\n\n"; - print HTML "<HR>\n" if $doindex and $index; - - # now convert this file - my $after_item; # set to true after an =item - warn "Converting input file $podfile\n" if $verbose; - foreach my $i (0..$#poddata){ - $ptQuote = 0; # status of quote conversion - - $_ = $poddata[$i]; - $paragraph = $i+1; - if (/^(=.*)/s) { # is it a pod directive? - $ignore = 0; - $after_item = 0; - $_ = $1; - if (/^=begin\s+(\S+)\s*(.*)/si) {# =begin - process_begin($1, $2); - } elsif (/^=end\s+(\S+)\s*(.*)/si) {# =end - process_end($1, $2); - } elsif (/^=cut/) { # =cut - process_cut(); - } elsif (/^=pod/) { # =pod - process_pod(); - } else { - next if @begin_stack && $begin_stack[-1] ne 'html'; - - if (/^=(head[1-6])\s+(.*\S)/s) { # =head[1-6] heading - process_head( $1, $2, $doindex && $index ); - } elsif (/^=item\s*(.*\S)?/sm) { # =item text - warn "$0: $podfile: =item without bullet, number or text" - . " in paragraph $paragraph.\n" if !defined($1) or $1 eq ''; - process_item( $1 ); - $after_item = 1; - } elsif (/^=over\s*(.*)/) { # =over N - process_over(); - } elsif (/^=back/) { # =back - process_back(); - } elsif (/^=for\s+(\S+)\s*(.*)/si) {# =for - process_for($1,$2); - } else { - /^=(\S*)\s*/; - warn "$0: $podfile: unknown pod directive '$1' in " - . "paragraph $paragraph. ignoring.\n"; - } - } - $top = 0; - } - else { - next if $ignore; - next if @begin_stack && $begin_stack[-1] ne 'html'; - my $text = $_; - if( $text =~ /\A\s+/ ){ - process_pre( \$text ); - print HTML "<PRE>\n$text</PRE>\n"; - - } else { - process_text( \$text ); - - # experimental: check for a paragraph where all lines - # have some ...\t...\t...\n pattern - if( $text =~ /\t/ ){ - my @lines = split( "\n", $text ); - if( @lines > 1 ){ - my $all = 2; - foreach my $line ( @lines ){ - if( $line =~ /\S/ && $line !~ /\t/ ){ - $all--; - last if $all == 0; - } - } - if( $all > 0 ){ - $text =~ s/\t+/<TD>/g; - $text =~ s/^/<TR><TD>/gm; - $text = '<TABLE CELLSPACING=0 CELLPADDING=0>' . - $text . '</TABLE>'; - } - } - } - ## end of experimental - - if( $after_item ){ - print HTML "$text\n"; - $after_lpar = 1; - } else { - print HTML "<P>$text</P>\n"; - } - } - $after_item = 0; - } - } - - # finish off any pending directives - finish_list(); - - # link to page index - print HTML "<P><A HREF=\"#__index__\"><SMALL>$backlink</SMALL></A></P>\n" - if $doindex and $index and $backlink; - - print HTML <<END_OF_TAIL; -$block -</BODY> - -</HTML> -END_OF_TAIL - - # close the html file - close(HTML); - - warn "Finished\n" if $verbose; -} - -############################################################################## - -my $usage; # see below -sub usage { - my $podfile = shift; - warn "$0: $podfile: @_\n" if @_; - die $usage; -} - -$usage =<<END_OF_USAGE; -Usage: $0 --help --htmlroot=<name> --infile=<name> --outfile=<name> - --podpath=<name>:...:<name> --podroot=<name> - --libpods=<name>:...:<name> --recurse --verbose --index - --netscape --norecurse --noindex - - --backlink - set text for "back to top" links (default: none). - --css - stylesheet URL - --flush - flushes the item and directory caches. - --[no]header - produce block header/footer (default is no headers). - --help - prints this message. - --htmldir - directory for resulting HTML files. - --htmlroot - http-server base directory from which all relative paths - in podpath stem (default is /). - --[no]index - generate an index at the top of the resulting html - (default behaviour). - --infile - filename for the pod to convert (input taken from stdin - by default). - --libpods - colon-separated list of pages to search for =item pod - directives in as targets of C<> and implicit links (empty - by default). note, these are not filenames, but rather - page names like those that appear in L<> links. - --[no]netscape - will use netscape html directives when applicable. - (default is not to use them). - --outfile - filename for the resulting html file (output sent to - stdout by default). - --podpath - colon-separated list of directories containing library - pods (empty by default). - --podroot - filesystem base directory from which all relative paths - in podpath stem (default is .). - --[no]quiet - supress some benign warning messages (default is off). - --[no]recurse - recurse on those subdirectories listed in podpath - (default behaviour). - --title - title that will appear in resulting html file. - --[no]verbose - self-explanatory (off by default). - -END_OF_USAGE - -sub parse_command_line { - my ($opt_backlink,$opt_css,$opt_flush,$opt_header,$opt_help,$opt_htmldir, - $opt_htmlroot,$opt_index,$opt_infile,$opt_libpods,$opt_netscape, - $opt_outfile,$opt_podpath,$opt_podroot,$opt_quiet,$opt_recurse, - $opt_title,$opt_verbose); - - unshift @ARGV, split ' ', $Config{pod2html} if $Config{pod2html}; - my $result = GetOptions( - 'backlink=s' => \$opt_backlink, - 'css=s' => \$opt_css, - 'flush' => \$opt_flush, - 'header!' => \$opt_header, - 'help' => \$opt_help, - 'htmldir=s' => \$opt_htmldir, - 'htmlroot=s' => \$opt_htmlroot, - 'index!' => \$opt_index, - 'infile=s' => \$opt_infile, - 'libpods=s' => \$opt_libpods, - 'netscape!' => \$opt_netscape, - 'outfile=s' => \$opt_outfile, - 'podpath=s' => \$opt_podpath, - 'podroot=s' => \$opt_podroot, - 'quiet!' => \$opt_quiet, - 'recurse!' => \$opt_recurse, - 'title=s' => \$opt_title, - 'verbose!' => \$opt_verbose, - ); - usage("-", "invalid parameters") if not $result; - - usage("-") if defined $opt_help; # see if the user asked for help - $opt_help = ""; # just to make -w shut-up. - - @podpath = split(":", $opt_podpath) if defined $opt_podpath; - @libpods = split(":", $opt_libpods) if defined $opt_libpods; - - $backlink = $opt_backlink if defined $opt_backlink; - $css = $opt_css if defined $opt_css; - $header = $opt_header if defined $opt_header; - $htmldir = $opt_htmldir if defined $opt_htmldir; - $htmlroot = $opt_htmlroot if defined $opt_htmlroot; - $doindex = $opt_index if defined $opt_index; - $podfile = $opt_infile if defined $opt_infile; - $netscape = $opt_netscape if defined $opt_netscape; - $htmlfile = $opt_outfile if defined $opt_outfile; - $podroot = $opt_podroot if defined $opt_podroot; - $quiet = $opt_quiet if defined $opt_quiet; - $recurse = $opt_recurse if defined $opt_recurse; - $title = $opt_title if defined $opt_title; - $verbose = $opt_verbose if defined $opt_verbose; - - warn "Flushing item and directory caches\n" - if $opt_verbose && defined $opt_flush; - unlink($dircache, $itemcache) if defined $opt_flush; -} - - -my $saved_cache_key; - -sub get_cache { - my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_; - my @cache_key_args = @_; - - # A first-level cache: - # Don't bother reading the cache files if they still apply - # and haven't changed since we last read them. - - my $this_cache_key = cache_key(@cache_key_args); - - return if $saved_cache_key and $this_cache_key eq $saved_cache_key; - - # load the cache of %pages and %items if possible. $tests will be - # non-zero if successful. - my $tests = 0; - if (-f $dircache && -f $itemcache) { - warn "scanning for item cache\n" if $verbose; - $tests = load_cache($dircache, $itemcache, $podpath, $podroot); - } - - # if we didn't succeed in loading the cache then we must (re)build - # %pages and %items. - if (!$tests) { - warn "scanning directories in pod-path\n" if $verbose; - scan_podpath($podroot, $recurse, 0); - } - $saved_cache_key = cache_key(@cache_key_args); -} - -sub cache_key { - my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_; - return join('!', $dircache, $itemcache, $recurse, - @$podpath, $podroot, stat($dircache), stat($itemcache)); -} - -# -# load_cache - tries to find if the caches stored in $dircache and $itemcache -# are valid caches of %pages and %items. if they are valid then it loads -# them and returns a non-zero value. -# -sub load_cache { - my($dircache, $itemcache, $podpath, $podroot) = @_; - my($tests); - local $_; - - $tests = 0; - - open(CACHE, "<$itemcache") || - die "$0: error opening $itemcache for reading: $!\n"; - $/ = "\n"; - - # is it the same podpath? - $_ = <CACHE>; - chomp($_); - $tests++ if (join(":", @$podpath) eq $_); - - # is it the same podroot? - $_ = <CACHE>; - chomp($_); - $tests++ if ($podroot eq $_); - - # load the cache if its good - if ($tests != 2) { - close(CACHE); - return 0; - } - - warn "loading item cache\n" if $verbose; - while (<CACHE>) { - /(.*?) (.*)$/; - $items{$1} = $2; - } - close(CACHE); - - warn "scanning for directory cache\n" if $verbose; - open(CACHE, "<$dircache") || - die "$0: error opening $dircache for reading: $!\n"; - $/ = "\n"; - $tests = 0; - - # is it the same podpath? - $_ = <CACHE>; - chomp($_); - $tests++ if (join(":", @$podpath) eq $_); - - # is it the same podroot? - $_ = <CACHE>; - chomp($_); - $tests++ if ($podroot eq $_); - - # load the cache if its good - if ($tests != 2) { - close(CACHE); - return 0; - } - - warn "loading directory cache\n" if $verbose; - while (<CACHE>) { - /(.*?) (.*)$/; - $pages{$1} = $2; - } - - close(CACHE); - - return 1; -} - -# -# scan_podpath - scans the directories specified in @podpath for directories, -# .pod files, and .pm files. it also scans the pod files specified in -# @libpods for =item directives. -# -sub scan_podpath { - my($podroot, $recurse, $append) = @_; - my($pwd, $dir); - my($libpod, $dirname, $pod, @files, @poddata); - - unless($append) { - %items = (); - %pages = (); - } - - # scan each directory listed in @podpath - $pwd = getcwd(); - chdir($podroot) - || die "$0: error changing to directory $podroot: $!\n"; - foreach $dir (@podpath) { - scan_dir($dir, $recurse); - } - - # scan the pods listed in @libpods for =item directives - foreach $libpod (@libpods) { - # if the page isn't defined then we won't know where to find it - # on the system. - next unless defined $pages{$libpod} && $pages{$libpod}; - - # if there is a directory then use the .pod and .pm files within it. - # NOTE: Only finds the first so-named directory in the tree. -# if ($pages{$libpod} =~ /([^:]*[^(\.pod|\.pm)]):/) { - if ($pages{$libpod} =~ /([^:]*(?<!\.pod)(?<!\.pm)):/) { - # find all the .pod and .pm files within the directory - $dirname = $1; - opendir(DIR, $dirname) || - die "$0: error opening directory $dirname: $!\n"; - @files = grep(/(\.pod|\.pm)\z/ && ! -d $_, readdir(DIR)); - closedir(DIR); - - # scan each .pod and .pm file for =item directives - foreach $pod (@files) { - open(POD, "<$dirname/$pod") || - die "$0: error opening $dirname/$pod for input: $!\n"; - @poddata = <POD>; - close(POD); - clean_data( \@poddata ); - - scan_items( \%items, "$dirname/$pod", @poddata); - } - - # use the names of files as =item directives too. -### Don't think this should be done this way - confuses issues.(WL) -### foreach $pod (@files) { -### $pod =~ /^(.*)(\.pod|\.pm)$/; -### $items{$1} = "$dirname/$1.html" if $1; -### } - } elsif ($pages{$libpod} =~ /([^:]*\.pod):/ || - $pages{$libpod} =~ /([^:]*\.pm):/) { - # scan the .pod or .pm file for =item directives - $pod = $1; - open(POD, "<$pod") || - die "$0: error opening $pod for input: $!\n"; - @poddata = <POD>; - close(POD); - clean_data( \@poddata ); - - scan_items( \%items, "$pod", @poddata); - } else { - warn "$0: shouldn't be here (line ".__LINE__."\n"; - } - } - @poddata = (); # clean-up a bit - - chdir($pwd) - || die "$0: error changing to directory $pwd: $!\n"; - - # cache the item list for later use - warn "caching items for later use\n" if $verbose; - open(CACHE, ">$itemcache") || - die "$0: error open $itemcache for writing: $!\n"; - - print CACHE join(":", @podpath) . "\n$podroot\n"; - foreach my $key (keys %items) { - print CACHE "$key $items{$key}\n"; - } - - close(CACHE); - - # cache the directory list for later use - warn "caching directories for later use\n" if $verbose; - open(CACHE, ">$dircache") || - die "$0: error open $dircache for writing: $!\n"; - - print CACHE join(":", @podpath) . "\n$podroot\n"; - foreach my $key (keys %pages) { - print CACHE "$key $pages{$key}\n"; - } - - close(CACHE); -} - -# -# scan_dir - scans the directory specified in $dir for subdirectories, .pod -# files, and .pm files. notes those that it finds. this information will -# be used later in order to figure out where the pages specified in L<> -# links are on the filesystem. -# -sub scan_dir { - my($dir, $recurse) = @_; - my($t, @subdirs, @pods, $pod, $dirname, @dirs); - local $_; - - @subdirs = (); - @pods = (); - - opendir(DIR, $dir) || - die "$0: error opening directory $dir: $!\n"; - while (defined($_ = readdir(DIR))) { - if (-d "$dir/$_" && $_ ne "." && $_ ne "..") { # directory - $pages{$_} = "" unless defined $pages{$_}; - $pages{$_} .= "$dir/$_:"; - push(@subdirs, $_); - } elsif (/\.pod\z/) { # .pod - s/\.pod\z//; - $pages{$_} = "" unless defined $pages{$_}; - $pages{$_} .= "$dir/$_.pod:"; - push(@pods, "$dir/$_.pod"); - } elsif (/\.html\z/) { # .html - s/\.html\z//; - $pages{$_} = "" unless defined $pages{$_}; - $pages{$_} .= "$dir/$_.pod:"; - } elsif (/\.pm\z/) { # .pm - s/\.pm\z//; - $pages{$_} = "" unless defined $pages{$_}; - $pages{$_} .= "$dir/$_.pm:"; - push(@pods, "$dir/$_.pm"); - } - } - closedir(DIR); - - # recurse on the subdirectories if necessary - if ($recurse) { - foreach my $subdir (@subdirs) { - scan_dir("$dir/$subdir", $recurse); - } - } -} - -# -# scan_headings - scan a pod file for head[1-6] tags, note the tags, and -# build an index. -# -sub scan_headings { - my($sections, @data) = @_; - my($tag, $which_head, $otitle, $listdepth, $index); - - # here we need local $ignore = 0; - # unfortunately, we can't have it, because $ignore is lexical - $ignore = 0; - - $listdepth = 0; - $index = ""; - - # scan for =head directives, note their name, and build an index - # pointing to each of them. - foreach my $line (@data) { - if ($line =~ /^=(head)([1-6])\s+(.*)/) { - ($tag, $which_head, $otitle) = ($1,$2,$3); - - my $title = depod( $otitle ); - my $name = htmlify( $title ); - $$sections{$name} = 1; - $title = process_text( \$otitle ); - - while ($which_head != $listdepth) { - if ($which_head > $listdepth) { - $index .= "\n" . ("\t" x $listdepth) . "<UL>\n"; - $listdepth++; - } elsif ($which_head < $listdepth) { - $listdepth--; - $index .= "\n" . ("\t" x $listdepth) . "</UL>\n"; - } - } - - $index .= "\n" . ("\t" x $listdepth) . "<LI>" . - "<A HREF=\"#" . $name . "\">" . - $title . "</A></LI>"; - } - } - - # finish off the lists - while ($listdepth--) { - $index .= "\n" . ("\t" x $listdepth) . "</UL>\n"; - } - - # get rid of bogus lists - $index =~ s,\t*<UL>\s*</UL>\n,,g; - - $ignore = 1; # restore old value; - - return $index; -} - -# -# scan_items - scans the pod specified by $pod for =item directives. we -# will use this information later on in resolving C<> links. -# -sub scan_items { - my( $itemref, $pod, @poddata ) = @_; - my($i, $item); - local $_; - - $pod =~ s/\.pod\z//; - $pod .= ".html" if $pod; - - foreach $i (0..$#poddata) { - my $txt = depod( $poddata[$i] ); - - # figure out what kind of item it is. - # Build string for referencing this item. - if ( $txt =~ /\A=item\s+\*\s*(.*)\Z/s ) { # bullet - next unless $1; - $item = $1; - } elsif( $txt =~ /\A=item\s+(?>\d+\.?)\s*(.*)\Z/s ) { # numbered list - $item = $1; - } elsif( $txt =~ /\A=item\s+(.*)\Z/s ) { # plain item - $item = $1; - } else { - next; - } - my $fid = fragment_id( $item ); - $$itemref{$fid} = "$pod" if $fid; - } -} - -# -# process_head - convert a pod head[1-6] tag and convert it to HTML format. -# -sub process_head { - my($tag, $heading, $hasindex) = @_; - - # figure out the level of the =head - $tag =~ /head([1-6])/; - my $level = $1; - - if( $listlevel ){ - warn "$0: $podfile: unterminated list at =head in paragraph $paragraph. ignoring.\n"; - while( $listlevel ){ - process_back(); - } - } - - print HTML "<P>\n"; - if( $level == 1 && ! $top ){ - print HTML "<A HREF=\"#__index__\"><SMALL>$backlink</SMALL></A>\n" - if $hasindex and $backlink; - print HTML "<HR>\n" - } - - my $name = htmlify( depod( $heading ) ); - my $convert = process_text( \$heading ); - print HTML "<H$level><A NAME=\"$name\">$convert</A></H$level>\n"; -} - - -# -# emit_item_tag - print an =item's text -# Note: The global $EmittedItem is used for inhibiting self-references. -# -my $EmittedItem; - -sub emit_item_tag($$$){ - my( $otext, $text, $compact ) = @_; - my $item = fragment_id( $text ); - - $EmittedItem = $item; - ### print STDERR "emit_item_tag=$item ($text)\n"; - - print HTML '<STRONG>'; - if ($items_named{$item}++) { - print HTML process_text( \$otext ); - } else { - my $name = 'item_' . $item; - print HTML qq{<A NAME="$name">}, process_text( \$otext ), '</A>'; - } - print HTML "</STRONG><BR>\n"; - undef( $EmittedItem ); -} - -sub emit_li { - my( $tag ) = @_; - if( $items_seen[$listlevel]++ == 0 ){ - push( @listend, "</$tag>" ); - print HTML "<$tag>\n"; - } - print HTML $tag eq 'DL' ? '<DT>' : '<LI>'; -} - -# -# process_item - convert a pod item tag and convert it to HTML format. -# -sub process_item { - my( $otext ) = @_; - - # lots of documents start a list without doing an =over. this is - # bad! but, the proper thing to do seems to be to just assume - # they did do an =over. so warn them once and then continue. - if( $listlevel == 0 ){ - warn "$0: $podfile: unexpected =item directive in paragraph $paragraph. ignoring.\n"; - process_over(); - } - - # formatting: insert a paragraph if preceding item has >1 paragraph - if( $after_lpar ){ - print HTML "<P></P>\n"; - $after_lpar = 0; - } - - # remove formatting instructions from the text - my $text = depod( $otext ); - - # all the list variants: - if( $text =~ /\A\*/ ){ # bullet - emit_li( 'UL' ); - if ($text =~ /\A\*\s+(.+)\Z/s ) { # with additional text - my $tag = $1; - $otext =~ s/\A\*\s+//; - emit_item_tag( $otext, $tag, 1 ); - } - - } elsif( $text =~ /\A\d+/ ){ # numbered list - emit_li( 'OL' ); - if ($text =~ /\A(?>\d+\.?)\s*(.+)\Z/s ) { # with additional text - my $tag = $1; - $otext =~ s/\A\d+\.?\s*//; - emit_item_tag( $otext, $tag, 1 ); - } - - } else { # definition list - emit_li( 'DL' ); - if ($text =~ /\A(.+)\Z/s ){ # should have text - emit_item_tag( $otext, $text, 1 ); - } - print HTML '<DD>'; - } - print HTML "\n"; -} - -# -# process_over - process a pod over tag and start a corresponding HTML list. -# -sub process_over { - # start a new list - $listlevel++; - push( @items_seen, 0 ); - $after_lpar = 0; -} - -# -# process_back - process a pod back tag and convert it to HTML format. -# -sub process_back { - if( $listlevel == 0 ){ - warn "$0: $podfile: unexpected =back directive in paragraph $paragraph. ignoring.\n"; - return; - } - - # close off the list. note, I check to see if $listend[$listlevel] is - # defined because an =item directive may have never appeared and thus - # $listend[$listlevel] may have never been initialized. - $listlevel--; - if( defined $listend[$listlevel] ){ - print HTML '<P></P>' if $after_lpar; - print HTML $listend[$listlevel]; - print HTML "\n"; - pop( @listend ); - } - $after_lpar = 0; - - # clean up item count - pop( @items_seen ); -} - -# -# process_cut - process a pod cut tag, thus start ignoring pod directives. -# -sub process_cut { - $ignore = 1; -} - -# -# process_pod - process a pod pod tag, thus stop ignoring pod directives -# until we see a corresponding cut. -# -sub process_pod { - # no need to set $ignore to 0 cause the main loop did it -} - -# -# process_for - process a =for pod tag. if it's for html, spit -# it out verbatim, if illustration, center it, otherwise ignore it. -# -sub process_for { - my($whom, $text) = @_; - if ( $whom =~ /^(pod2)?html$/i) { - print HTML $text; - } elsif ($whom =~ /^illustration$/i) { - 1 while chomp $text; - for my $ext (qw[.png .gif .jpeg .jpg .tga .pcl .bmp]) { - $text .= $ext, last if -r "$text$ext"; - } - print HTML qq{<p align = "center"><img src = "$text" alt = "$text illustration"></p>}; - } -} - -# -# process_begin - process a =begin pod tag. this pushes -# whom we're beginning on the begin stack. if there's a -# begin stack, we only print if it us. -# -sub process_begin { - my($whom, $text) = @_; - $whom = lc($whom); - push (@begin_stack, $whom); - if ( $whom =~ /^(pod2)?html$/) { - print HTML $text if $text; - } -} - -# -# process_end - process a =end pod tag. pop the -# begin stack. die if we're mismatched. -# -sub process_end { - my($whom, $text) = @_; - $whom = lc($whom); - if ($begin_stack[-1] ne $whom ) { - die "Unmatched begin/end at chunk $paragraph\n" - } - pop( @begin_stack ); -} - -# -# process_pre - indented paragraph, made into <PRE></PRE> -# -sub process_pre { - my( $text ) = @_; - my( $rest ); - return if $ignore; - - $rest = $$text; - - # insert spaces in place of tabs - $rest =~ s#.*# - my $line = $&; - 1 while $line =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; - $line; - #eg; - - # convert some special chars to HTML escapes - $rest =~ s/&/&/g; - $rest =~ s/</</g; - $rest =~ s/>/>/g; - $rest =~ s/"/"/g; - - # try and create links for all occurrences of perl.* within - # the preformatted text. - $rest =~ s{ - (\s*)(perl\w+) - }{ - if ( defined $pages{$2} ){ # is a link - qq($1<A HREF="$htmlroot/$pages{$2}">$2</A>); - } elsif (defined $pages{dosify($2)}) { # is a link - qq($1<A HREF="$htmlroot/$pages{dosify($2)}">$2</A>); - } else { - "$1$2"; - } - }xeg; - $rest =~ s{ - (<A\ HREF="?) ([^>:]*:)? ([^>:]*) \.pod: ([^>:]*:)? - }{ - my $url ; - if ( $htmlfileurl ne '' ){ - # Here, we take advantage of the knowledge - # that $htmlfileurl ne '' implies $htmlroot eq ''. - # Since $htmlroot eq '', we need to prepend $htmldir - # on the fron of the link to get the absolute path - # of the link's target. We check for a leading '/' - # to avoid corrupting links that are #, file:, etc. - my $old_url = $3 ; - $old_url = "$htmldir$old_url" if $old_url =~ m{^\/}; - $url = relativize_url( "$old_url.html", $htmlfileurl ); - } else { - $url = "$3.html" ; - } - "$1$url" ; - }xeg; - - # Look for embedded URLs and make them into links. We don't - # relativize them since they are best left as the author intended. - - my $urls = '(' . join ('|', qw{ - http - telnet - mailto - news - gopher - file - wais - ftp - } ) - . ')'; - - my $ltrs = '\w'; - my $gunk = '/#~:.?+=&%@!\-'; - my $punc = '.:?\-'; - my $any = "${ltrs}${gunk}${punc}"; - - $rest =~ s{ - \b # start at word boundary - ( # begin $1 { - $urls : # need resource and a colon - (?!:) # Ignore File::, among others. - [$any] +? # followed by on or more - # of any valid character, but - # be conservative and take only - # what you need to.... - ) # end $1 } - (?= # look-ahead non-consumptive assertion - [$punc]* # either 0 or more puntuation - [^$any] # followed by a non-url char - | # or else - $ # then end of the string - ) - }{<A HREF="$1">$1</A>}igox; - - # text should be as it is (verbatim) - $$text = $rest; -} - - -# -# pure text processing -# -# pure_text/inIS_text: differ with respect to automatic C<> recognition. -# we don't want this to happen within IS -# -sub pure_text($){ - my $text = shift(); - process_puretext( $text, \$ptQuote, 1 ); -} - -sub inIS_text($){ - my $text = shift(); - process_puretext( $text, \$ptQuote, 0 ); -} - -# -# process_puretext - process pure text (without pod-escapes) converting -# double-quotes and handling implicit C<> links. -# -sub process_puretext { - my($text, $quote, $notinIS) = @_; - - ## Guessing at func() or [$@%&]*var references in plain text is destined - ## to produce some strange looking ref's. uncomment to disable: - ## $notinIS = 0; - - my(@words, $lead, $trail); - - # convert double-quotes to single-quotes - if( $$quote && $text =~ s/"/''/s ){ - $$quote = 0; - } - while ($text =~ s/"([^"]*)"/``$1''/sg) {}; - $$quote = 1 if $text =~ s/"/``/s; - - # keep track of leading and trailing white-space - $lead = ($text =~ s/\A(\s+)//s ? $1 : ""); - $trail = ($text =~ s/(\s+)\Z//s ? $1 : ""); - - # split at space/non-space boundaries - @words = split( /(?<=\s)(?=\S)|(?<=\S)(?=\s)/, $text ); - - # process each word individually - foreach my $word (@words) { - # skip space runs - next if $word =~ /^\s*$/; - # see if we can infer a link - if( $notinIS && $word =~ /^(\w+)\((.*)\)$/ ) { - # has parenthesis so should have been a C<> ref - ## try for a pagename (perlXXX(1))? - my( $func, $args ) = ( $1, $2 ); - if( $args =~ /^\d+$/ ){ - my $url = page_sect( $word, '' ); - if( defined $url ){ - $word = "<A HREF=\"$url\">the $word manpage</A>"; - next; - } - } - ## try function name for a link, append tt'ed argument list - $word = emit_C( $func, '', "($args)"); - -#### disabled. either all (including $\W, $\w+{.*} etc.) or nothing. -## } elsif( $notinIS && $word =~ /^[\$\@%&*]+\w+$/) { -## # perl variables, should be a C<> ref -## $word = emit_C( $word ); - - } elsif ($word =~ m,^\w+://\w,) { - # looks like a URL - # Don't relativize it: leave it as the author intended - $word = qq(<A HREF="$word">$word</A>); - } elsif ($word =~ /[\w.-]+\@[\w-]+\.\w/) { - # looks like an e-mail address - my ($w1, $w2, $w3) = ("", $word, ""); - ($w1, $w2, $w3) = ("(", $1, ")$2") if $word =~ /^\((.*?)\)(,?)/; - ($w1, $w2, $w3) = ("<", $1, ">$2") if $word =~ /^<(.*?)>(,?)/; - $word = qq($w1<A HREF="mailto:$w2">$w2</A>$w3); - } elsif ($word !~ /[a-z]/ && $word =~ /[A-Z]/) { # all uppercase? - $word = html_escape($word) if $word =~ /["&<>]/; - $word = "\n<FONT SIZE=-1>$word</FONT>" if $netscape; - } else { - $word = html_escape($word) if $word =~ /["&<>]/; - } - } - - # put everything back together - return $lead . join( '', @words ) . $trail; -} - - -# -# process_text - handles plaintext that appears in the input pod file. -# there may be pod commands embedded within the text so those must be -# converted to html commands. -# - -sub process_text1($$;$$); -sub pattern ($) { $_[0] ? '[^\S\n]+'.('>' x ($_[0] + 1)) : '>' } -sub closing ($) { local($_) = shift; (defined && s/\s+$//) ? length : 0 } - -sub process_text { - return if $ignore; - my( $tref ) = @_; - my $res = process_text1( 0, $tref ); - $$tref = $res; -} - -sub process_text1($$;$$){ - my( $lev, $rstr, $func, $closing ) = @_; - my $res = ''; - - unless (defined $func) { - $func = ''; - $lev++; - } - - if( $func eq 'B' ){ - # B<text> - boldface - $res = '<STRONG>' . process_text1( $lev, $rstr ) . '</STRONG>'; - - } elsif( $func eq 'C' ){ - # C<code> - can be a ref or <CODE></CODE> - # need to extract text - my $par = go_ahead( $rstr, 'C', $closing ); - - ## clean-up of the link target - my $text = depod( $par ); - - ### my $x = $par =~ /[BI]</ ? 'yes' : 'no' ; - ### print STDERR "-->call emit_C($par) lev=$lev, par with BI=$x\n"; - - $res = emit_C( $text, $lev > 1 || ($par =~ /[BI]</) ); - - } elsif( $func eq 'E' ){ - # E<x> - convert to character - $$rstr =~ s/^([^>]*)>//; - my $escape = $1; - $escape =~ s/^(\d+|X[\dA-F]+)$/#$1/i; - $res = "&$escape;"; - - } elsif( $func eq 'F' ){ - # F<filename> - italizice - $res = '<EM>' . process_text1( $lev, $rstr ) . '</EM>'; - - } elsif( $func eq 'I' ){ - # I<text> - italizice - $res = '<EM>' . process_text1( $lev, $rstr ) . '</EM>'; - - } elsif( $func eq 'L' ){ - # L<link> - link - ## L<text|cross-ref> => produce text, use cross-ref for linking - ## L<cross-ref> => make text from cross-ref - ## need to extract text - my $par = go_ahead( $rstr, 'L', $closing ); - - # some L<>'s that shouldn't be: - # a) full-blown URL's are emitted as-is - if( $par =~ m{^\w+://}s ){ - return make_URL_href( $par ); - } - # b) C<...> is stripped and treated as C<> - if( $par =~ /^C<(.*)>$/ ){ - my $text = depod( $1 ); - return emit_C( $text, $lev > 1 || ($par =~ /[BI]</) ); - } - - # analyze the contents - $par =~ s/\n/ /g; # undo word-wrapped tags - my $opar = $par; - my $linktext; - if( $par =~ s{^([^|]+)\|}{} ){ - $linktext = $1; - } - - # make sure sections start with a / - $par =~ s{^"}{/"}; - - my( $page, $section, $ident ); - - # check for link patterns - if( $par =~ m{^([^/]+?)/(?!")(.*?)$} ){ # name/ident - # we've got a name/ident (no quotes) - ( $page, $ident ) = ( $1, $2 ); - ### print STDERR "--> L<$par> to page $page, ident $ident\n"; - - } elsif( $par =~ m{^(.*?)/"?(.*?)"?$} ){ # [name]/"section" - # even though this should be a "section", we go for ident first - ( $page, $ident ) = ( $1, $2 ); - ### print STDERR "--> L<$par> to page $page, section $section\n"; - - } elsif( $par =~ /\s/ ){ # this must be a section with missing quotes - ( $page, $section ) = ( '', $par ); - ### print STDERR "--> L<$par> to void page, section $section\n"; - - } else { - ( $page, $section ) = ( $par, '' ); - ### print STDERR "--> L<$par> to page $par, void section\n"; - } - - # now, either $section or $ident is defined. the convoluted logic - # below tries to resolve L<> according to what the user specified. - # failing this, we try to find the next best thing... - my( $url, $ltext, $fid ); - - RESOLVE: { - if( defined $ident ){ - ## try to resolve $ident as an item - ( $url, $fid ) = coderef( $page, $ident ); - if( $url ){ - if( ! defined( $linktext ) ){ - $linktext = $ident; - $linktext .= " in " if $ident && $page; - $linktext .= "the $page manpage" if $page; - } - ### print STDERR "got coderef url=$url\n"; - last RESOLVE; - } - ## no luck: go for a section (auto-quoting!) - $section = $ident; - } - ## now go for a section - my $htmlsection = htmlify( $section ); - $url = page_sect( $page, $htmlsection ); - if( $url ){ - if( ! defined( $linktext ) ){ - $linktext = $section; - $linktext .= " in " if $section && $page; - $linktext .= "the $page manpage" if $page; - } - ### print STDERR "got page/section url=$url\n"; - last RESOLVE; - } - ## no luck: go for an ident - if( $section ){ - $ident = $section; - } else { - $ident = $page; - $page = undef(); - } - ( $url, $fid ) = coderef( $page, $ident ); - if( $url ){ - if( ! defined( $linktext ) ){ - $linktext = $ident; - $linktext .= " in " if $ident && $page; - $linktext .= "the $page manpage" if $page; - } - ### print STDERR "got section=>coderef url=$url\n"; - last RESOLVE; - } - - # warning; show some text. - $linktext = $opar unless defined $linktext; - warn "$0: $podfile: cannot resolve L<$opar> in paragraph $paragraph."; - } - - # now we have an URL or just plain code - $$rstr = $linktext . '>' . $$rstr; - if( defined( $url ) ){ - $res = "<A HREF=\"$url\">" . process_text1( $lev, $rstr ) . '</A>'; - } else { - $res = '<EM>' . process_text1( $lev, $rstr ) . '</EM>'; - } - - } elsif( $func eq 'S' ){ - # S<text> - non-breaking spaces - $res = process_text1( $lev, $rstr ); - $res =~ s/ / /g; - - } elsif( $func eq 'X' ){ - # X<> - ignore - $$rstr =~ s/^[^>]*>//; - - } elsif( $func eq 'Z' ){ - # Z<> - empty - warn "$0: $podfile: invalid X<> in paragraph $paragraph." - unless $$rstr =~ s/^>//; - - } else { - my $term = pattern $closing; - while( $$rstr =~ s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)//s ){ - # all others: either recurse into new function or - # terminate at closing angle bracket(s) - my $pt = $1; - $pt .= $2 if !$3 && $lev == 1; - $res .= $lev == 1 ? pure_text( $pt ) : inIS_text( $pt ); - return $res if !$3 && $lev > 1; - if( $3 ){ - $res .= process_text1( $lev, $rstr, $3, closing $4 ); - } - } - if( $lev == 1 ){ - $res .= pure_text( $$rstr ); - } else { - warn "$0: $podfile: undelimited $func<> in paragraph $paragraph."; - } - } - return $res; -} - -# -# go_ahead: extract text of an IS (can be nested) -# -sub go_ahead($$$){ - my( $rstr, $func, $closing ) = @_; - my $res = ''; - my @closing = ($closing); - while( $$rstr =~ - s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|@{[pattern $closing[0]]})//s ){ - $res .= $1; - unless( $3 ){ - shift @closing; - return $res unless @closing; - } else { - unshift @closing, closing $4; - } - $res .= $2; - } - warn "$0: $podfile: undelimited $func<> in paragraph $paragraph."; - return $res; -} - -# -# emit_C - output result of C<text> -# $text is the depod-ed text -# -sub emit_C($;$$){ - my( $text, $nocode, $args ) = @_; - $args = '' unless defined $args; - my $res; - my( $url, $fid ) = coderef( undef(), $text ); - - # need HTML-safe text - my $linktext = html_escape( "$text$args" ); - - if( defined( $url ) && - (!defined( $EmittedItem ) || $EmittedItem ne $fid ) ){ - $res = "<A HREF=\"$url\"><CODE>$linktext</CODE></A>"; - } elsif( 0 && $nocode ){ - $res = $linktext; - } else { - $res = "<CODE>$linktext</CODE>"; - } - return $res; -} - -# -# html_escape: make text safe for HTML -# -sub html_escape { - my $rest = $_[0]; - $rest =~ s/&/&/g; - $rest =~ s/</</g; - $rest =~ s/>/>/g; - $rest =~ s/"/"/g; - return $rest; -} - - -# -# dosify - convert filenames to 8.3 -# -sub dosify { - my($str) = @_; - return lc($str) if $^O eq 'VMS'; # VMS just needs casing - if ($Is83) { - $str = lc $str; - $str =~ s/(\.\w+)/substr ($1,0,4)/ge; - $str =~ s/(\w+)/substr ($1,0,8)/ge; - } - return $str; -} - -# -# page_sect - make an URL from the text of a L<> -# -sub page_sect($$) { - my( $page, $section ) = @_; - my( $linktext, $page83, $link); # work strings - - # check if we know that this is a section in this page - if (!defined $pages{$page} && defined $sections{$page}) { - $section = $page; - $page = ""; - ### print STDERR "reset page='', section=$section\n"; - } - - $page83=dosify($page); - $page=$page83 if (defined $pages{$page83}); - if ($page eq "") { - $link = "#" . htmlify( $section ); - } elsif ( $page =~ /::/ ) { - $page =~ s,::,/,g; - # Search page cache for an entry keyed under the html page name, - # then look to see what directory that page might be in. NOTE: - # this will only find one page. A better solution might be to produce - # an intermediate page that is an index to all such pages. - my $page_name = $page ; - $page_name =~ s,^.*/,,s ; - if ( defined( $pages{ $page_name } ) && - $pages{ $page_name } =~ /([^:]*$page)\.(?:pod|pm):/ - ) { - $page = $1 ; - } - else { - # NOTE: This branch assumes that all A::B pages are located in - # $htmlroot/A/B.html . This is often incorrect, since they are - # often in $htmlroot/lib/A/B.html or such like. Perhaps we could - # analyze the contents of %pages and figure out where any - # cousins of A::B are, then assume that. So, if A::B isn't found, - # but A::C is found in lib/A/C.pm, then A::B is assumed to be in - # lib/A/B.pm. This is also limited, but it's an improvement. - # Maybe a hints file so that the links point to the correct places - # nonetheless? - - } - $link = "$htmlroot/$page.html"; - $link .= "#" . htmlify( $section ) if ($section); - } elsif (!defined $pages{$page}) { - $link = ""; - } else { - $section = htmlify( $section ) if $section ne ""; - ### print STDERR "...section=$section\n"; - - # if there is a directory by the name of the page, then assume that an - # appropriate section will exist in the subdirectory -# if ($section ne "" && $pages{$page} =~ /([^:]*[^(\.pod|\.pm)]):/) { - if ($section ne "" && $pages{$page} =~ /([^:]*(?<!\.pod)(?<!\.pm)):/) { - $link = "$htmlroot/$1/$section.html"; - ### print STDERR "...link=$link\n"; - - # since there is no directory by the name of the page, the section will - # have to exist within a .html of the same name. thus, make sure there - # is a .pod or .pm that might become that .html - } else { - $section = "#$section" if $section; - ### print STDERR "...section=$section\n"; - - # check if there is a .pod with the page name - if ($pages{$page} =~ /([^:]*)\.pod:/) { - $link = "$htmlroot/$1.html$section"; - } elsif ($pages{$page} =~ /([^:]*)\.pm:/) { - $link = "$htmlroot/$1.html$section"; - } else { - $link = ""; - } - } - } - - if ($link) { - # Here, we take advantage of the knowledge that $htmlfileurl ne '' - # implies $htmlroot eq ''. This means that the link in question - # needs a prefix of $htmldir if it begins with '/'. The test for - # the initial '/' is done to avoid '#'-only links, and to allow - # for other kinds of links, like file:, ftp:, etc. - my $url ; - if ( $htmlfileurl ne '' ) { - $link = "$htmldir$link" if $link =~ m{^/}s; - $url = relativize_url( $link, $htmlfileurl ); -# print( " b: [$link,$htmlfileurl,$url]\n" ); - } - else { - $url = $link ; - } - return $url; - - } else { - return undef(); - } -} - -# -# relativize_url - convert an absolute URL to one relative to a base URL. -# Assumes both end in a filename. -# -sub relativize_url { - my ($dest,$source) = @_ ; - - my ($dest_volume,$dest_directory,$dest_file) = - File::Spec::Unix->splitpath( $dest ) ; - $dest = File::Spec::Unix->catpath( $dest_volume, $dest_directory, '' ) ; - - my ($source_volume,$source_directory,$source_file) = - File::Spec::Unix->splitpath( $source ) ; - $source = File::Spec::Unix->catpath( $source_volume, $source_directory, '' ) ; - - my $rel_path = '' ; - if ( $dest ne '' ) { - $rel_path = File::Spec::Unix->abs2rel( $dest, $source ) ; - } - - if ( $rel_path ne '' && - substr( $rel_path, -1 ) ne '/' && - substr( $dest_file, 0, 1 ) ne '#' - ) { - $rel_path .= "/$dest_file" ; - } - else { - $rel_path .= "$dest_file" ; - } - - return $rel_path ; -} - - -# -# coderef - make URL from the text of a C<> -# -sub coderef($$){ - my( $page, $item ) = @_; - my( $url ); - - my $fid = fragment_id( $item ); - if( defined( $page ) ){ - # we have been given a $page... - $page =~ s{::}{/}g; - - # Do we take it? Item could be a section! - my $base = $items{$fid} || ""; - $base =~ s{[^/]*/}{}; - if( $base ne "$page.html" ){ - ### print STDERR "coderef( $page, $item ): items{$fid} = $items{$fid} = $base => discard page!\n"; - $page = undef(); - } - - } else { - # no page - local items precede cached items - if( defined( $fid ) ){ - if( exists $local_items{$fid} ){ - $page = $local_items{$fid}; - } else { - $page = $items{$fid}; - } - } - } - - # if there was a pod file that we found earlier with an appropriate - # =item directive, then create a link to that page. - if( defined $page ){ - if( $page ){ - if( exists $pages{$page} and $pages{$page} =~ /([^:.]*)\.[^:]*:/){ - $page = $1 . '.html'; - } - my $link = "$htmlroot/$page#item_$fid"; - - # Here, we take advantage of the knowledge that $htmlfileurl - # ne '' implies $htmlroot eq ''. - if ( $htmlfileurl ne '' ) { - $link = "$htmldir$link" ; - $url = relativize_url( $link, $htmlfileurl ) ; - } else { - $url = $link ; - } - } else { - $url = "#item_" . $fid; - } - - confess "url has space: $url" if $url =~ /"[^"]*\s[^"]*"/; - } - return( $url, $fid ); -} - - - -# -# Adapted from Nick Ing-Simmons' PodToHtml package. -sub relative_url { - my $source_file = shift ; - my $destination_file = shift; - - my $source = URI::file->new_abs($source_file); - my $uo = URI::file->new($destination_file,$source)->abs; - return $uo->rel->as_string; -} - - -# -# finish_list - finish off any pending HTML lists. this should be called -# after the entire pod file has been read and converted. -# -sub finish_list { - while ($listlevel > 0) { - print HTML "</DL>\n"; - $listlevel--; - } -} - -# -# htmlify - converts a pod section specification to a suitable section -# specification for HTML. Note that we keep spaces and special characters -# except ", ? (Netscape problem) and the hyphen (writer's problem...). -# -sub htmlify { - my( $heading) = @_; - $heading =~ s/(\s+)/ /g; - $heading =~ s/\s+\Z//; - $heading =~ s/\A\s+//; - # The hyphen is a disgrace to the English language. - $heading =~ s/[-"?]//g; - $heading = lc( $heading ); - return $heading; -} - -# -# depod - convert text by eliminating all interior sequences -# Note: can be called with copy or modify semantics -# -my %E2c; -$E2c{lt} = '<'; -$E2c{gt} = '>'; -$E2c{sol} = '/'; -$E2c{verbar} = '|'; -$E2c{amp} = '&'; # in Tk's pods - -sub depod1($;$$); - -sub depod($){ - my $string; - if( ref( $_[0] ) ){ - $string = ${$_[0]}; - ${$_[0]} = depod1( \$string ); - } else { - $string = $_[0]; - depod1( \$string ); - } -} - -sub depod1($;$$){ - my( $rstr, $func, $closing ) = @_; - my $res = ''; - return $res unless defined $$rstr; - if( ! defined( $func ) ){ - # skip to next begin of an interior sequence - while( $$rstr =~ s/\A(.*?)([BCEFILSXZ])<(<+[^\S\n]+)?// ){ - # recurse into its text - $res .= $1 . depod1( $rstr, $2, closing $3); - } - $res .= $$rstr; - } elsif( $func eq 'E' ){ - # E<x> - convert to character - $$rstr =~ s/^([^>]*)>//; - $res .= $E2c{$1} || ""; - } elsif( $func eq 'X' ){ - # X<> - ignore - $$rstr =~ s/^[^>]*>//; - } elsif( $func eq 'Z' ){ - # Z<> - empty - $$rstr =~ s/^>//; - } else { - # all others: either recurse into new function or - # terminate at closing angle bracket - my $term = pattern $closing; - while( $$rstr =~ s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)// ){ - $res .= $1; - last unless $3; - $res .= depod1( $rstr, $3, closing $4 ); - } - ## If we're here and $2 ne '>': undelimited interior sequence. - ## Ignored, as this is called without proper indication of where we are. - ## Rely on process_text to produce diagnostics. - } - return $res; -} - -# -# fragment_id - construct a fragment identifier from: -# a) =item text -# b) contents of C<...> -# -my @hc; -sub fragment_id { - my $text = shift(); - $text =~ s/\s+\Z//s; - if( $text ){ - # a method or function? - return $1 if $text =~ /(\w+)\s*\(/; - return $1 if $text =~ /->\s*(\w+)\s*\(?/; - - # a variable name? - return $1 if $text =~ /^([$@%*]\S+)/; - - # some pattern matching operator? - return $1 if $text =~ m|^(\w+/).*/\w*$|; - - # fancy stuff... like "do { }" - return $1 if $text =~ m|^(\w+)\s*{.*}$|; - - # honour the perlfunc manpage: func [PAR[,[ ]PAR]...] - # and some funnies with ... Module ... - return $1 if $text =~ m{^([a-z\d]+)(\s+[A-Z\d,/& ]+)?$}; - return $1 if $text =~ m{^([a-z\d]+)\s+Module(\s+[A-Z\d,/& ]+)?$}; - - # text? normalize! - $text =~ s/\s+/_/sg; - $text =~ s{(\W)}{ - defined( $hc[ord($1)] ) ? $hc[ord($1)] - : ( $hc[ord($1)] = sprintf( "%%%02X", ord($1) ) ) }gxe; - $text = substr( $text, 0, 50 ); - } else { - return undef(); - } -} - -# -# make_URL_href - generate HTML href from URL -# Special treatment for CGI queries. -# -sub make_URL_href($){ - my( $url ) = @_; - if( $url !~ - s{^(http:[-\w/#~:.+=&%@!]+)(\?.*)$}{<A HREF="$1$2">$1</A>}i ){ - $url = "<A HREF=\"$url\">$url</A>"; - } - return $url; -} - -1; diff --git a/contrib/perl5/lib/Pod/InputObjects.pm b/contrib/perl5/lib/Pod/InputObjects.pm deleted file mode 100644 index 352373b..0000000 --- a/contrib/perl5/lib/Pod/InputObjects.pm +++ /dev/null @@ -1,933 +0,0 @@ -############################################################################# -# 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 vars qw($VERSION); -$VERSION = 1.13; ## 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 - -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: - -=over 4 - -=begin __PRIVATE__ - -=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. - -=end __PRIVATE__ - -=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 - -############################################################################# - -use strict; -#use diagnostics; -#use Carp; - -############################################################################# - -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) ? $_[0] : 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 an 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 havent 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 = \⊤ - -##--------------------------------------------------------------------------- - -=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 and !(ref $ptree[0]) and !(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; - for (@_) { - next unless length; - if (@ptree and !(ref $ptree[-1]) and !(ref $_)) { - $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 (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 - -See L<Pod::Parser>, L<Pod::Select> - -=head1 AUTHOR - -Brad Appleton E<lt>bradapp@enteract.comE<gt> - -=cut - -1; diff --git a/contrib/perl5/lib/Pod/LaTeX.pm b/contrib/perl5/lib/Pod/LaTeX.pm deleted file mode 100644 index c909d21..0000000 --- a/contrib/perl5/lib/Pod/LaTeX.pm +++ /dev/null @@ -1,1591 +0,0 @@ -package Pod::LaTeX; - -# Copyright (C) 2000 by Tim Jenness <t.jenness@jach.hawaii.edu> -# All Rights Reserved. - -=head1 NAME - -Pod::LaTeX - Convert Pod data to formatted Latex - -=head1 SYNOPSIS - - use Pod::LaTeX; - my $parser = Pod::LaTeX->new ( ); - - $parser->parse_from_filehandle; - - $parser->parse_from_file ('file.pod', 'file.tex'); - -=head1 DESCRIPTION - -C<Pod::LaTeX> is a module to convert documentation in the Pod format -into Latex. The L<B<pod2latex>|pod2latex> X<pod2latex> command uses -this module for translation. - -C<Pod::LaTeX> is a derived class from L<Pod::Select|Pod::Select>. - -=cut - - -use strict; -require Pod::ParseUtils; -use base qw/ Pod::Select /; - -# use Data::Dumper; # for debugging -use Carp; - -use vars qw/ $VERSION %HTML_Escapes @LatexSections /; - -$VERSION = '0.53'; - -# Definitions of =headN -> latex mapping -@LatexSections = (qw/ - chapter - section - subsection - subsubsection - paragraph - subparagraph - /); - -# Standard escape sequences converted to Latex -# Up to "yuml" these are taken from the original pod2latex -# command written by Taro Kawagish (kawagish@imslab.co.jp) - -%HTML_Escapes = ( - 'amp' => '&', # ampersand - 'lt' => '$<$', # ' left chevron, less-than - 'gt' => '$>$', # ' right chevron, greater-than - 'quot' => '"', # double quote - 'sol' => '/', - 'verbar' => '$|$', - - "Aacute" => "\\'{A}", # capital A, acute accent - "aacute" => "\\'{a}", # small a, acute accent - "Acirc" => "\\^{A}", # capital A, circumflex accent - "acirc" => "\\^{a}", # small a, circumflex accent - "AElig" => '\\AE', # capital AE diphthong (ligature) - "aelig" => '\\ae', # small ae diphthong (ligature) - "Agrave" => "\\`{A}", # capital A, grave accent - "agrave" => "\\`{a}", # small a, grave accent - "Aring" => '\\u{A}', # capital A, ring - "aring" => '\\u{a}', # small a, ring - "Atilde" => '\\~{A}', # capital A, tilde - "atilde" => '\\~{a}', # small a, tilde - "Auml" => '\\"{A}', # capital A, dieresis or umlaut mark - "auml" => '\\"{a}', # small a, dieresis or umlaut mark - "Ccedil" => '\\c{C}', # capital C, cedilla - "ccedil" => '\\c{c}', # small c, cedilla - "Eacute" => "\\'{E}", # capital E, acute accent - "eacute" => "\\'{e}", # small e, acute accent - "Ecirc" => "\\^{E}", # capital E, circumflex accent - "ecirc" => "\\^{e}", # small e, circumflex accent - "Egrave" => "\\`{E}", # capital E, grave accent - "egrave" => "\\`{e}", # small e, grave accent - "ETH" => '\\OE', # capital Eth, Icelandic - "eth" => '\\oe', # small eth, Icelandic - "Euml" => '\\"{E}', # capital E, dieresis or umlaut mark - "euml" => '\\"{e}', # small e, dieresis or umlaut mark - "Iacute" => "\\'{I}", # capital I, acute accent - "iacute" => "\\'{i}", # small i, acute accent - "Icirc" => "\\^{I}", # capital I, circumflex accent - "icirc" => "\\^{i}", # small i, circumflex accent - "Igrave" => "\\`{I}", # capital I, grave accent - "igrave" => "\\`{i}", # small i, grave accent - "Iuml" => '\\"{I}', # capital I, dieresis or umlaut mark - "iuml" => '\\"{i}', # small i, dieresis or umlaut mark - "Ntilde" => '\\~{N}', # capital N, tilde - "ntilde" => '\\~{n}', # small n, tilde - "Oacute" => "\\'{O}", # capital O, acute accent - "oacute" => "\\'{o}", # small o, acute accent - "Ocirc" => "\\^{O}", # capital O, circumflex accent - "ocirc" => "\\^{o}", # small o, circumflex accent - "Ograve" => "\\`{O}", # capital O, grave accent - "ograve" => "\\`{o}", # small o, grave accent - "Oslash" => "\\O", # capital O, slash - "oslash" => "\\o", # small o, slash - "Otilde" => "\\~{O}", # capital O, tilde - "otilde" => "\\~{o}", # small o, tilde - "Ouml" => '\\"{O}', # capital O, dieresis or umlaut mark - "ouml" => '\\"{o}', # small o, dieresis or umlaut mark - "szlig" => '\\ss{}', # small sharp s, German (sz ligature) - "THORN" => '\\L', # capital THORN, Icelandic - "thorn" => '\\l',, # small thorn, Icelandic - "Uacute" => "\\'{U}", # capital U, acute accent - "uacute" => "\\'{u}", # small u, acute accent - "Ucirc" => "\\^{U}", # capital U, circumflex accent - "ucirc" => "\\^{u}", # small u, circumflex accent - "Ugrave" => "\\`{U}", # capital U, grave accent - "ugrave" => "\\`{u}", # small u, grave accent - "Uuml" => '\\"{U}', # capital U, dieresis or umlaut mark - "uuml" => '\\"{u}', # small u, dieresis or umlaut mark - "Yacute" => "\\'{Y}", # capital Y, acute accent - "yacute" => "\\'{y}", # small y, acute accent - "yuml" => '\\"{y}', # small y, dieresis or umlaut mark - - # Added by TimJ - - "iexcl" => '!`', # inverted exclamation mark -# "cent" => ' ', # cent sign - "pound" => '\pounds', # (UK) pound sign -# "curren" => ' ', # currency sign -# "yen" => ' ', # yen sign -# "brvbar" => ' ', # broken vertical bar - "sect" => '\S', # section sign - "uml" => '\"{}', # diaresis - "copy" => '\copyright', # Copyright symbol -# "ordf" => ' ', # feminine ordinal indicator - "laquo" => '$\ll$', # ' # left pointing double angle quotation mark - "not" => '$\neg$', # ' # not sign - "shy" => '-', # soft hyphen -# "reg" => ' ', # registered trademark - "macr" => '$^-$', # ' # macron, overline - "deg" => '$^\circ$', # ' # degree sign - "plusmn" => '$\pm$', # ' # plus-minus sign - "sup2" => '$^2$', # ' # superscript 2 - "sup3" => '$^3$', # ' # superscript 3 - "acute" => "\\'{}", # acute accent - "micro" => '$\mu$', # micro sign - "para" => '\P', # pilcrow sign = paragraph sign - "middot" => '$\cdot$', # middle dot = Georgian comma - "cedil" => '\c{}', # cedilla - "sup1" => '$^1$', # ' # superscript 1 -# "ordm" => ' ', # masculine ordinal indicator - "raquo" => '$\gg$', # ' # right pointing double angle quotation mark - "frac14" => '$\frac{1}{4}$', # ' # vulgar fraction one quarter - "frac12" => '$\frac{1}{2}$', # ' # vulgar fraction one half - "frac34" => '$\frac{3}{4}$', # ' # vulgar fraction three quarters - "iquest" => "?'", # inverted question mark - "times" => '$\times$', # ' # multiplication sign - "divide" => '$\div$', # division sign - - # Greek letters using HTML codes - "alpha" => '$\alpha$', # ' - "beta" => '$\beta$', # ' - "gamma" => '$\gamma$', # ' - "delta" => '$\delta$', # ' - "epsilon"=> '$\epsilon$', # ' - "zeta" => '$\zeta$', # ' - "eta" => '$\eta$', # ' - "theta" => '$\theta$', # ' - "iota" => '$\iota$', # ' - "kappa" => '$\kappa$', # ' - "lambda" => '$\lambda$', # ' - "mu" => '$\mu$', # ' - "nu" => '$\nu$', # ' - "xi" => '$\xi$', # ' - "omicron"=> '$o$', # ' - "pi" => '$\pi$', # ' - "rho" => '$\rho$', # ' - "sigma" => '$\sigma$', # ' - "tau" => '$\tau$', # ' - "upsilon"=> '$\upsilon$', # ' - "phi" => '$\phi$', # ' - "chi" => '$\chi$', # ' - "psi" => '$\psi$', # ' - "omega" => '$\omega$', # ' - - "Alpha" => '$A$', # ' - "Beta" => '$B$', # ' - "Gamma" => '$\Gamma$', # ' - "Delta" => '$\Delta$', # ' - "Epsilon"=> '$E$', # ' - "Zeta" => '$Z$', # ' - "Eta" => '$H$', # ' - "Theta" => '$\Theta$', # ' - "Iota" => '$I$', # ' - "Kappa" => '$K$', # ' - "Lambda" => '$\Lambda$', # ' - "Mu" => '$M$', # ' - "Nu" => '$N$', # ' - "Xi" => '$\Xi$', # ' - "Omicron"=> '$O$', # ' - "Pi" => '$\Pi$', # ' - "Rho" => '$R$', # ' - "Sigma" => '$\Sigma$', # ' - "Tau" => '$T$', # ' - "Upsilon"=> '$\Upsilon$', # ' - "Phi" => '$\Phi$', # ' - "Chi" => '$X$', # ' - "Psi" => '$\Psi$', # ' - "Omega" => '$\Omega$', # ' - - -); - - -=head1 OBJECT METHODS - -The following methods are provided in this module. Methods inherited -from C<Pod::Select> are not described in the public interface. - -=over 4 - -=begin __PRIVATE__ - -=item C<initialize> - -Initialise the object. This method is subclassed from C<Pod::Parser>. -The base class method is invoked. This method defines the default -behaviour of the object unless overridden by supplying arguments to -the constructor. - -Internal settings are defaulted as well as the public instance data. -Internal hash values are accessed directly (rather than through -a method) and start with an underscore. - -This method should not be invoked by the user directly. - -=end __PRIVATE__ - -=cut - - - -# - An array for nested lists - -# Arguments have already been read by this point - -sub initialize { - my $self = shift; - - # print Dumper($self); - - # Internals - $self->{_Lists} = []; # For nested lists - $self->{_suppress_all_para} = 0; # For =begin blocks - $self->{_suppress_next_para} = 0; # For =for blocks - $self->{_dont_modify_any_para}=0; # For =begin blocks - $self->{_dont_modify_next_para}=0; # For =for blocks - $self->{_CURRENT_HEAD1} = ''; # Name of current HEAD1 section - - # Options - only initialise if not already set - - # Cause the '=head1 NAME' field to be treated specially - # The contents of the NAME paragraph will be converted - # to a section title. All subsequent =head1 will be converted - # to =head2 and down. Will not affect =head1's prior to NAME - # Assumes: 'Module - purpose' format - # Also creates a purpose field - # The name is used for Labeling of the subsequent subsections - $self->{ReplaceNAMEwithSection} = 0 - unless exists $self->{ReplaceNAMEwithSection}; - $self->{AddPreamble} = 1 # make full latex document - unless exists $self->{AddPreamble}; - $self->{StartWithNewPage} = 0 # Start new page for pod section - unless exists $self->{StartWithNewPage}; - $self->{TableOfContents} = 0 # Add table of contents - unless exists $self->{TableOfContents}; # only relevent if AddPreamble=1 - $self->{AddPostamble} = 1 # Add closing latex code at end - unless exists $self->{AddPostamble}; # effectively end{document} and index - $self->{MakeIndex} = 1 # Add index (only relevant AddPostamble - unless exists $self->{MakeIndex}; # and AddPreamble) - - $self->{UniqueLabels} = 1 # Use label unique for each pod - unless exists $self->{UniqueLabels}; # either based on the filename - # or supplied - - # Control the level of =head1. default is \section - # - $self->{Head1Level} = 1 # Offset in latex sections - unless exists $self->{Head1Level}; # 0 is chapter, 2 is subsection - - # Control at which level numbering of sections is turned off - # ie subsection becomes subsection* - # The numbering is relative to the latex sectioning commands - # and is independent of Pod heading level - # default is to number \section but not \subsection - $self->{LevelNoNum} = 2 - unless exists $self->{LevelNoNum}; - - # Label to be used as prefix to all internal section names - # If not defined will attempt to derive it from the filename - # This can not happen when running parse_from_filehandle though - # hence the ability to set the label externally - # The label could then be Pod::Parser_DESCRIPTION or somesuch - - $self->{Label} = undef # label to be used as prefix - unless exists $self->{Label}; # to all internal section names - - # These allow the caller to add arbritrary latex code to - # start and end of document. AddPreamble and AddPostamble are ignored - # if these are set. - # Also MakeIndex and TableOfContents are also ignored. - $self->{UserPreamble} = undef # User supplied start (AddPreamble =1) - unless exists $self->{Label}; - $self->{UserPostamble} = undef # Use supplied end (AddPostamble=1) - unless exists $self->{Label}; - - # Run base initialize - $self->SUPER::initialize; - -} - -=back - -=head2 Data Accessors - -The following methods are provided for accessing instance data. These -methods should be used for accessing configuration parameters rather -than assuming the object is a hash. - -Default values can be supplied by using these names as keys to a hash -of arguments when using the C<new()> constructor. - -=over 4 - -=item B<AddPreamble> - -Logical to control whether a C<latex> preamble is to be written. -If true, a valid C<latex> preamble is written before the pod data is written. -This is similar to: - - \documentclass{article} - \begin{document} - -but will be more complicated if table of contents and indexing are required. -Can be used to set or retrieve the current value. - - $add = $parser->AddPreamble(); - $parser->AddPreamble(1); - -If used in conjunction with C<AddPostamble> a full latex document will -be written that could be immediately processed by C<latex>. - -=cut - -sub AddPreamble { - my $self = shift; - if (@_) { - $self->{AddPreamble} = shift; - } - return $self->{AddPreamble}; -} - -=item B<AddPostamble> - -Logical to control whether a standard C<latex> ending is written to the output -file after the document has been processed. -In its simplest form this is simply: - - \end{document} - -but can be more complicated if a index is required. -Can be used to set or retrieve the current value. - - $add = $parser->AddPostamble(); - $parser->AddPostamble(1); - -If used in conjunction with C<AddPreaamble> a full latex document will -be written that could be immediately processed by C<latex>. - -=cut - -sub AddPostamble { - my $self = shift; - if (@_) { - $self->{AddPostamble} = shift; - } - return $self->{AddPostamble}; -} - -=item B<Head1Level> - -The C<latex> sectioning level that should be used to correspond to -a pod C<=head1> directive. This can be used, for example, to turn -a C<=head1> into a C<latex> C<subsection>. This should hold a number -corresponding to the required position in an array containing the -following elements: - - [0] chapter - [1] section - [2] subsection - [3] subsubsection - [4] paragraph - [5] subparagraph - -Can be used to set or retrieve the current value: - - $parser->Head1Level(2); - $sect = $parser->Head1Level; - -Setting this number too high can result in sections that may not be reproducible -in the expected way. For example, setting this to 4 would imply that C<=head3> -do not have a corresponding C<latex> section (C<=head1> would correspond to -a C<paragraph>). - -A check is made to ensure that the supplied value is an integer in the -range 0 to 5. - -Default is for a value of 1 (i.e. a C<section>). - -=cut - -sub Head1Level { - my $self = shift; - if (@_) { - my $arg = shift; - if ($arg =~ /^\d$/ && $arg <= $#LatexSections) { - $self->{Head1Level} = $arg; - } else { - carp "Head1Level supplied ($arg) must be integer in range 0 to ".$#LatexSections . "- Ignoring\n"; - } - } - return $self->{Head1Level}; -} - -=item B<Label> - -This is the label that is prefixed to all C<latex> label and index -entries to make them unique. In general, pods have similarly titled -sections (NAME, DESCRIPTION etc) and a C<latex> label will be multiply -defined if more than one pod document is to be included in a single -C<latex> file. To overcome this, this label is prefixed to a label -whenever a label is required (joined with an underscore) or to an -index entry (joined by an exclamation mark which is the normal index -separator). For example, C<\label{text}> becomes C<\label{Label_text}>. - -Can be used to set or retrieve the current value: - - $label = $parser->Label; - $parser->Label($label); - -This label is only used if C<UniqueLabels> is true. -Its value is set automatically from the C<NAME> field -if C<ReplaceNAMEwithSection> is true. If this is not the case -it must be set manually before starting the parse. - -Default value is C<undef>. - -=cut - -sub Label { - my $self = shift; - if (@_) { - $self->{Label} = shift; - } - return $self->{Label}; -} - -=item B<LevelNoNum> - -Control the point at which C<latex> section numbering is turned off. -For example, this can be used to make sure that C<latex> sections -are numbered but subsections are not. - -Can be used to set or retrieve the current value: - - $lev = $parser->LevelNoNum; - $parser->LevelNoNum(2); - -The argument must be an integer between 0 and 5 and is the same as the -number described in C<Head1Level> method description. The number has -nothing to do with the pod heading number, only the C<latex> sectioning. - -Default is 2. (i.e. C<latex> subsections are written as C<subsection*> -but sections are numbered). - -=cut - -sub LevelNoNum { - my $self = shift; - if (@_) { - $self->{LevelNoNum} = shift; - } - return $self->{LevelNoNum}; -} - -=item B<MakeIndex> - -Controls whether C<latex> commands for creating an index are to be inserted -into the preamble and postamble - - $makeindex = $parser->MakeIndex; - $parser->MakeIndex(0); - -Irrelevant if both C<AddPreamble> and C<AddPostamble> are false (or equivalently, -C<UserPreamble> and C<UserPostamble> are set). - -Default is for an index to be created. - -=cut - -sub MakeIndex { - my $self = shift; - if (@_) { - $self->{MakeIndex} = shift; - } - return $self->{MakeIndex}; -} - -=item B<ReplaceNAMEwithSection> - -This controls whether the C<NAME> section in the pod is to be translated -literally or converted to a slightly modified output where the section -name is the pod name rather than "NAME". - -If true, the pod segment - - =head1 NAME - - pod::name - purpose - - =head1 SYNOPSIS - -is converted to the C<latex> - - \section{pod::name\label{pod_name}\index{pod::name}} - - Purpose - - \subsection*{SYNOPSIS\label{pod_name_SYNOPSIS}% - \index{pod::name!SYNOPSIS}} - -(dependent on the value of C<Head1Level> and C<LevelNoNum>). Note that -subsequent C<head1> directives translate to subsections rather than -sections and that the labels and index now include the pod name (dependent -on the value of C<UniqueLabels>). - -The C<Label> is set from the pod name regardless of any current value -of C<Label>. - - $mod = $parser->ReplaceNAMEwithSection; - $parser->ReplaceNAMEwithSection(0); - -Default is to translate the pod literally. - -=cut - -sub ReplaceNAMEwithSection { - my $self = shift; - if (@_) { - $self->{ReplaceNAMEwithSection} = shift; - } - return $self->{ReplaceNAMEwithSection}; -} - -=item B<StartWithNewPage> - -If true, each pod translation will begin with a C<latex> -C<\clearpage>. - - $parser->StartWithNewPage(1); - $newpage = $parser->StartWithNewPage; - -Default is false. - -=cut - -sub StartWithNewPage { - my $self = shift; - if (@_) { - $self->{StartWithNewPage} = shift; - } - return $self->{StartWithNewPage}; -} - -=item B<TableOfContents> - -If true, a table of contents will be created. -Irrelevant if C<AddPreamble> is false or C<UserPreamble> -is set. - - $toc = $parser->TableOfContents; - $parser->TableOfContents(1); - -Default is false. - -=cut - -sub TableOfContents { - my $self = shift; - if (@_) { - $self->{TableOfContents} = shift; - } - return $self->{TableOfContents}; -} - -=item B<UniqueLabels> - -If true, the translator will attempt to make sure that -each C<latex> label or index entry will be uniquely identified -by prefixing the contents of C<Label>. This allows -multiple documents to be combined without clashing -common labels such as C<DESCRIPTION> and C<SYNOPSIS> - - $parser->UniqueLabels(1); - $unq = $parser->UniqueLabels; - -Default is true. - -=cut - -sub UniqueLabels { - my $self = shift; - if (@_) { - $self->{UniqueLabels} = shift; - } - return $self->{UniqueLabels}; -} - -=item B<UserPreamble> - -User supplied C<latex> preamble. Added before the pod translation -data. - -If set, the contents will be prepended to the output file before the translated -data regardless of the value of C<AddPreamble>. -C<MakeIndex> and C<TableOfContents> will also be ignored. - -=cut - -sub UserPreamble { - my $self = shift; - if (@_) { - $self->{UserPreamble} = shift; - } - return $self->{UserPreamble}; -} - -=item B<UserPostamble> - -User supplied C<latex> postamble. Added after the pod translation -data. - -If set, the contents will be prepended to the output file after the translated -data regardless of the value of C<AddPostamble>. -C<MakeIndex> will also be ignored. - -=cut - -sub UserPostamble { - my $self = shift; - if (@_) { - $self->{UserPostamble} = shift; - } - return $self->{UserPostamble}; -} - -=begin __PRIVATE__ - -=item B<Lists> - -Contains details of the currently active lists. - The array contains C<Pod::List> objects. A new C<Pod::List> -object is created each time a list is encountered and it is -pushed onto this stack. When the list context ends, it -is popped from the stack. The array will be empty if no -lists are active. - -Returns array of list information in list context -Returns array ref in scalar context - -=cut - - - -sub lists { - my $self = shift; - return @{ $self->{_Lists} } if wantarray(); - return $self->{_Lists}; -} - -=end __PRIVATE__ - -=back - -=begin __PRIVATE__ - -=head2 Subclassed methods - -The following methods override methods provided in the C<Pod::Select> -base class. See C<Pod::Parser> and C<Pod::Select> for more information -on what these methods require. - -=over 4 - -=cut - -######### END ACCESSORS ################### - -# Opening pod - -=item B<begin_pod> - -Writes the C<latex> preamble if requested. - -=cut - -sub begin_pod { - my $self = shift; - - # Get the pod identification - # This should really come from the '=head1 NAME' paragraph - - my $infile = $self->input_file; - my $class = ref($self); - my $date = gmtime(time); - - # Comment message to say where this came from - my $comment = << "__TEX_COMMENT__"; -%% Latex generated from POD in document $infile -%% Using the perl module $class -%% Converted on $date -__TEX_COMMENT__ - - # Write the preamble - # If the caller has supplied one then we just use that - - my $preamble = ''; - if (defined $self->UserPreamble) { - - $preamble = $self->UserPreamble; - - # Add the description of where this came from - $preamble .= "\n$comment"; - - - } elsif ($self->AddPreamble) { - # Write our own preamble - - # Code to initialise index making - # Use an array so that we can prepend comment if required - my @makeidx = ( - '\usepackage{makeidx}', - '\makeindex', - ); - - unless ($self->MakeIndex) { - foreach (@makeidx) { - $_ = '%% ' . $_; - } - } - my $makeindex = join("\n",@makeidx) . "\n"; - - - # Table of contents - my $tableofcontents = '\tableofcontents'; - - $tableofcontents = '%% ' . $tableofcontents - unless $self->TableOfContents; - - # Roll our own - $preamble = << "__TEX_HEADER__"; -\\documentclass{article} - -$comment - -$makeindex - -\\begin{document} - -$tableofcontents - -__TEX_HEADER__ - - } - - # Write the header (blank if none) - $self->_output($preamble); - - # Start on new page if requested - $self->_output("\\clearpage\n") if $self->StartWithNewPage; - -} - - -=item B<end_pod> - -Write the closing C<latex> code. - -=cut - -sub end_pod { - my $self = shift; - - # End string - my $end = ''; - - # Use the user version of the postamble if deinfed - if (defined $self->UserPostamble) { - $end = $self->UserPostamble; - - $self->_output($end); - - } elsif ($self->AddPostamble) { - - # Check for index - my $makeindex = '\printindex'; - - $makeindex = '%% '. $makeindex unless $self->MakeIndex; - - $end = "$makeindex\n\n\\end{document}\n"; - } - - - $self->_output($end); - -} - -=item B<command> - -Process basic pod commands. - -=cut - -sub command { - my $self = shift; - my ($command, $paragraph, $line_num, $parobj) = @_; - - # return if we dont care - return if $command eq 'pod'; - - $paragraph = $self->_replace_special_chars($paragraph); - - # Interpolate pod sequences in paragraph - $paragraph = $self->interpolate($paragraph, $line_num); - - $paragraph =~ s/\s+$//; - - # Now run the command - if ($command eq 'over') { - - $self->begin_list($paragraph, $line_num); - - } elsif ($command eq 'item') { - - $self->add_item($paragraph, $line_num); - - } elsif ($command eq 'back') { - - $self->end_list($line_num); - - } elsif ($command eq 'head1') { - - # Store the name of the section - $self->{_CURRENT_HEAD1} = $paragraph; - - # Print it - $self->head(1, $paragraph, $parobj); - - } elsif ($command eq 'head2') { - - $self->head(2, $paragraph, $parobj); - - } elsif ($command eq 'head3') { - - $self->head(3, $paragraph, $parobj); - - } elsif ($command eq 'head4') { - - $self->head(4, $paragraph, $parobj); - - } elsif ($command eq 'head5') { - - $self->head(5, $paragraph, $parobj); - - } elsif ($command eq 'head6') { - - $self->head(6, $paragraph, $parobj); - - } elsif ($command eq 'begin') { - - # pass through if latex - if ($paragraph =~ /^latex/i) { - # Make sure that subsequent paragraphs are not modfied before printing - $self->{_dont_modify_any_para} = 1; - - } else { - # Suppress all subsequent paragraphs unless - # it is explcitly intended for latex - $self->{_suppress_all_para} = 1; - } - - } elsif ($command eq 'for') { - - # pass through if latex - if ($paragraph =~ /^latex/i) { - # Make sure that next paragraph is not modfied before printing - $self->{_dont_modify_next_para} = 1; - - } else { - # Suppress the next paragraph unless it is latex - $self->{_suppress_next_para} = 1 - } - - } elsif ($command eq 'end') { - - # Reset suppression - $self->{_suppress_all_para} = 0; - $self->{_dont_modify_any_para} = 0; - - } elsif ($command eq 'pod') { - - # Do nothing - - } else { - carp "Command $command not recognised at line $line_num\n"; - } - -} - -=item B<verbatim> - -Verbatim text - -=cut - -sub verbatim { - my $self = shift; - my ($paragraph, $line_num, $parobj) = @_; - - # Expand paragraph unless in =for or =begin block - if ($self->{_dont_modify_any_para} || $self->{_dont_modify_next_para}) { - # Just print as is - $self->_output($paragraph); - - # Reset flag if in =for - $self->{_dont_modify_next_para} = 0; - - } else { - - return if $paragraph =~ /^\s+$/; - - # Clean trailing space - $paragraph =~ s/\s+$//; - - # Clean tabs - $paragraph =~ s/\t/ /g; - - $self->_output('\begin{verbatim}' . "\n$paragraph\n". '\end{verbatim}'."\n"); - } -} - -=item B<textblock> - -Plain text paragraph. - -=cut - -sub textblock { - my $self = shift; - my ($paragraph, $line_num, $parobj) = @_; - - # print Dumper($self); - - # Expand paragraph unless in =for or =begin block - if ($self->{_dont_modify_any_para} || $self->{_dont_modify_next_para}) { - # Just print as is - $self->_output($paragraph); - - # Reset flag if in =for - $self->{_dont_modify_next_para} = 0; - - return; - } - - - # Escape latex special characters - $paragraph = $self->_replace_special_chars($paragraph); - - # Interpolate interior sequences - my $expansion = $self->interpolate($paragraph, $line_num); - $expansion =~ s/\s+$//; - - - # If we are replacing 'head1 NAME' with a section - # we need to look in the paragraph and rewrite things - # Need to make sure this is called only on the first paragraph - # following 'head1 NAME' and not on subsequent paragraphs that may be - # present. - if ($self->{_CURRENT_HEAD1} =~ /^NAME/i && $self->ReplaceNAMEwithSection()) { - - # Strip white space from start and end - $paragraph =~ s/^\s+//; - $paragraph =~ s/\s$//; - - # Split the string into 2 parts - my ($name, $purpose) = split(/\s+-\s+/, $expansion,2); - - # Now prevent this from triggering until a new head1 NAME is set - $self->{_CURRENT_HEAD1} = '_NAME'; - - # Might want to clear the Label() before doing this (CHECK) - - # Print the heading - $self->head(1, $name, $parobj); - - # Set the labeling in case we want unique names later - $self->Label( $self->_create_label( $name, 1 ) ); - - # Raise the Head1Level by one so that subsequent =head1 appear - # as subsections of the main name section unless we are already - # at maximum [Head1Level() could check this itself - CHECK] - $self->Head1Level( $self->Head1Level() + 1) - unless $self->Head1Level == $#LatexSections; - - # Now write out the new latex paragraph - $purpose = ucfirst($purpose); - $self->_output("\n\n$purpose\n\n"); - - } else { - # Just write the output - $self->_output("\n\n$expansion\n\n"); - } - -} - -=item B<interior_sequence> - -Interior sequence expansion - -=cut - -sub interior_sequence { - my $self = shift; - - my ($seq_command, $seq_argument, $pod_seq) = @_; - - if ($seq_command eq 'B') { - return "\\textbf{$seq_argument}"; - - } elsif ($seq_command eq 'I') { - return "\\textit{$seq_argument}"; - - } elsif ($seq_command eq 'E') { - - # If it is simply a number - if ($seq_argument =~ /^\d+$/) { - return chr($seq_argument); - # Look up escape in hash table - } elsif (exists $HTML_Escapes{$seq_argument}) { - return $HTML_Escapes{$seq_argument}; - - } else { - my ($file, $line) = $pod_seq->file_line(); - warn "Escape sequence $seq_argument not recognised at line $line of file $file\n"; - return; - } - - } elsif ($seq_command eq 'Z') { - - # Zero width space - return '$\!$'; # ' - - } elsif ($seq_command eq 'C') { - return "\\texttt{$seq_argument}"; - - } elsif ($seq_command eq 'F') { - return "\\emph{$seq_argument}"; - - } elsif ($seq_command eq 'S') { - # non breakable spaces - my $nbsp = '$\:$'; #' - - $seq_argument =~ s/\s/$nbsp/g; - return $seq_argument; - - } elsif ($seq_command eq 'L') { - - my $link = new Pod::Hyperlink($seq_argument); - - # undef on failure - unless (defined $link) { - carp $@; - return; - } - - # Handle internal links differently - my $type = $link->type; - my $page = $link->page; - - if ($type eq 'section' && $page eq '') { - # Use internal latex reference - my $node = $link->node; - - # Convert to a label - $node = $self->_create_label($node); - - return "\\S\\ref{$node}"; - - } else { - # Use default markup for external references - # (although Starlink would use \xlabel) - my $markup = $link->markup; - - my ($file, $line) = $pod_seq->file_line(); - - return $self->interpolate($link->markup, $line); - } - - - - } elsif ($seq_command eq 'P') { - # Special markup for Pod::Hyperlink - # Replace :: with / - my $link = $seq_argument; - $link =~ s/::/\//g; - - my $ref = "\\emph{$seq_argument}"; - return $ref; - - } elsif ($seq_command eq 'Q') { - # Special markup for Pod::Hyperlink - return "\\textsf{$seq_argument}\n"; - - } elsif ($seq_command eq 'X') { - # Index entries - - # use \index command - # I will let '!' go through for now - # not sure how sub categories are handled in X<> - my $index = $self->_create_index($seq_argument); - return "\\index{$index}\n"; - - } else { - carp "Unknown sequence $seq_command<$seq_argument>"; - } - -} - -=back - -=head2 List Methods - -Methods used to handle lists. - -=over 4 - -=item B<begin_list> - -Called when a new list is found (via the C<over> directive). -Creates a new C<Pod::List> object and stores it on the -list stack. - - $parser->begin_list($indent, $line_num); - -=cut - -sub begin_list { - my $self = shift; - my $indent = shift; - my $line_num = shift; - - # Indicate that a list should be started for the next item - # need to do this to work out the type of list - push ( @{$self->lists}, new Pod::List(-indent => $indent, - -start => $line_num, - -file => $self->input_file, - ) - ); - -} - -=item B<end_list> - -Called when the end of a list is found (the C<back> directive). -Pops the C<Pod::List> object off the stack of lists and writes -the C<latex> code required to close a list. - - $parser->end_list($line_num); - -=cut - -sub end_list { - my $self = shift; - my $line_num = shift; - - unless (defined $self->lists->[-1]) { - my $file = $self->input_file; - warn "No list is active at line $line_num (file=$file). Missing =over?\n"; - return; - } - - # What to write depends on list type - my $type = $self->lists->[-1]->type; - - # Dont write anything if the list type is not set - # iomplying that a list was created but no entries were - # placed in it (eg because of a =begin/=end combination) - $self->_output("\\end{$type}\n") - if (defined $type && length($type) > 0); - - # Clear list - pop(@{ $self->lists}); - -} - -=item B<add_item> - -Add items to the list. The first time an item is encountered -(determined from the state of the current C<Pod::List> object) -the type of list is determined (ordered, unnumbered or description) -and the relevant latex code issued. - - $parser->add_item($paragraph, $line_num); - -=cut - -sub add_item { - my $self = shift; - my $paragraph = shift; - my $line_num = shift; - - unless (defined $self->lists->[-1]) { - my $file = $self->input_file; - warn "List has already ended by line $line_num of file $file. Missing =over?\n"; - # Replace special chars -# $paragraph = $self->_replace_special_chars($paragraph); - $self->_output("$paragraph\n\n"); - return; - } - - # If paragraphs printing is turned off via =begin/=end or whatver - # simply return immediately - return if ($self->{_suppress_all_para} || $self->{_suppress_next_para}); - - # Check to see whether we are starting a new lists - if (scalar($self->lists->[-1]->item) == 0) { - - # Examine the paragraph to determine what type of list - # we have - $paragraph =~ s/\s+$//; - $paragraph =~ s/^\s+//; - - my $type; - if (substr($paragraph, 0,1) eq '*') { - $type = 'itemize'; - } elsif ($paragraph =~ /^\d/) { - $type = 'enumerate'; - } else { - $type = 'description'; - } - $self->lists->[-1]->type($type); - - $self->_output("\\begin{$type}\n"); - - } - - my $type = $self->lists->[-1]->type; - - if ($type eq 'description') { - # Handle long items - long items do not wrap - if (length($paragraph) < 40) { - # A real description list item - $self->_output("\\item[$paragraph] \\mbox{}"); - } else { - # The item is now simply bold text - $self->_output(qq{\\item \\textbf{$paragraph}}); - } - - } else { - # If the item was '* Something' we still need to write - # out the something - my $extra_info = $paragraph; - $extra_info =~ s/^\*\s*//; - $self->_output("\\item $extra_info"); - } - - # Store the item name in the object. Required so that - # we can tell if the list is new or not - $self->lists->[-1]->item($paragraph); - -} - -=back - -=head2 Methods for headings - -=over 4 - -=item B<head> - -Print a heading of the required level. - - $parser->head($level, $paragraph, $parobj); - -The first argument is the pod heading level. The second argument -is the contents of the heading. The 3rd argument is a Pod::Paragraph -object so that the line number can be extracted. - -=cut - -sub head { - my $self = shift; - my $num = shift; - my $paragraph = shift; - my $parobj = shift; - - # If we are replace 'head1 NAME' with a section - # we return immediately if we get it - return - if ($self->{_CURRENT_HEAD1} =~ /^NAME/i && $self->ReplaceNAMEwithSection()); - - # Create a label - my $label = $self->_create_label($paragraph); - - # Create an index entry - my $index = $self->_create_index($paragraph); - - # Work out position in the above array taking into account - # that =head1 is equivalent to $self->Head1Level - - my $level = $self->Head1Level() - 1 + $num; - - # Warn if heading to large - if ($num > $#LatexSections) { - my $line = $parobj->file_line; - my $file = $self->input_file; - warn "Heading level too large ($level) for LaTeX at line $line of file $file\n"; - $level = $#LatexSections; - } - - # Check to see whether section should be unnumbered - my $star = ($level >= $self->LevelNoNum ? '*' : ''); - - # Section - $self->_output("\\" .$LatexSections[$level] .$star ."{$paragraph\\label{".$label ."}\\index{".$index."}}"); - -} - - -=back - -=end __PRIVATE__ - -=begin __PRIVATE__ - -=head2 Internal methods - -Internal routines are described in this section. They do not form part of the -public interface. All private methods start with an underscore. - -=over 4 - -=item B<_output> - -Output text to the output filehandle. This method must be always be called -to output parsed text. - - $parser->_output($text); - -Does not write anything if a =begin or =for is active that should be -ignored. - -=cut - -sub _output { - my $self = shift; - my $text = shift; - - print { $self->output_handle } $text - unless $self->{_suppress_all_para} || - $self->{_suppress_next_para}; - - # Reset pargraph stuff for =for - $self->{_suppress_next_para} = 0 - if $self->{_suppress_next_para}; -} - - -=item B<_replace_special_chars> - -Subroutine to replace characters that are special in C<latex> -with the escaped forms - - $escaped = $parser->_replace_special_chars($paragraph); - -Need to call this routine before interior_sequences are munged but -not if verbatim. - -Special characters and the C<latex> equivalents are: - - } \} - { \{ - _ \_ - $ \$ - % \% - & \& - \ $\backslash$ - ^ \^{} - ~ \~{} - | $|$ - -=cut - -sub _replace_special_chars { - my $self = shift; - my $paragraph = shift; - - # Replace a \ with $\backslash$ - # This is made more complicated because the dollars will be escaped - # by the subsequent replacement. Easiest to add \backslash - # now and then add the dollars - $paragraph =~ s/\\/\\backslash/g; - - # Must be done after escape of \ since this command adds latex escapes - # Replace characters that can be escaped - $paragraph =~ s/([\$\#&%_{}])/\\$1/g; - - # Replace ^ characters with \^{} so that $^F works okay - $paragraph =~ s/(\^)/\\$1\{\}/g; - - # Replace tilde (~) with \texttt{\~{}} - $paragraph =~ s/~/\\texttt\{\\~\{\}\}/g; - - # Replace | with $|$ - $paragraph =~ s'\|'$|$'g; - - # Now add the dollars around each \backslash - $paragraph =~ s/(\\backslash)/\$$1\$/g; - - return $paragraph; -} - - -=item B<_create_label> - -Return a string that can be used as an internal reference -in a C<latex> document (i.e. accepted by the C<\label> command) - - $label = $parser->_create_label($string) - -If UniqueLabels is true returns a label prefixed by Label() -This can be suppressed with an optional second argument. - - $label = $parser->_create_label($string, $suppress); - -If a second argument is supplied (of any value including undef) -the Label() is never prefixed. This means that this routine can -be called to create a Label() without prefixing a previous setting. - -=cut - -sub _create_label { - my $self = shift; - my $paragraph = shift; - my $suppress = (@_ ? 1 : 0 ); - - # Remove latex commands - $paragraph = $self->_clean_latex_commands($paragraph); - - # Remove non alphanumerics from the label and replace with underscores - # want to protect '-' though so use negated character classes - $paragraph =~ s/[^-:\w]/_/g; - - # Multiple underscores will look unsightly so remove repeats - # This will also have the advantage of tidying up the end and - # start of string - $paragraph =~ s/_+/_/g; - - # If required need to make sure that the label is unique - # since it is possible to have multiple pods in a single - # document - if (!$suppress && $self->UniqueLabels() && defined $self->Label) { - $paragraph = $self->Label() .'_'. $paragraph; - } - - return $paragraph; -} - - -=item B<_create_index> - -Similar to C<_create_label> except an index entry is created. -If C<UniqueLabels> is true, the index entry is prefixed by -the current C<Label> and an exclamation mark. - - $ind = $parser->_create_index($paragraph); - -An exclamation mark is used by C<makeindex> to generate -sub-entries in an index. - -=cut - -sub _create_index { - my $self = shift; - my $paragraph = shift; - my $suppress = (@_ ? 1 : 0 ); - - # Remove latex commands - $paragraph = $self->_clean_latex_commands($paragraph); - - # If required need to make sure that the index entry is unique - # since it is possible to have multiple pods in a single - # document - if (!$suppress && $self->UniqueLabels() && defined $self->Label) { - $paragraph = $self->Label() .'!'. $paragraph; - } - - # Need to replace _ with space - $paragraph =~ s/_/ /g; - - return $paragraph; - -} - -=item B<_clean_latex_commands> - -Removes latex commands from text. The latex command is assumed to be of the -form C<\command{ text }>. "C<text>" is retained - - $clean = $parser->_clean_latex_commands($text); - -=cut - -sub _clean_latex_commands { - my $self = shift; - my $paragraph = shift; - - # Remove latex commands of the form \text{ } - # and replace with the contents of the { } - # need to make this non-greedy so that it can handle - # "\text{a} and \text2{b}" - # without converting it to - # "a} and \text2{b" - # This match will still get into trouble if \} is present - # This is not vital since the subsequent replacement of non-alphanumeric - # characters will tidy it up anyway - $paragraph =~ s/\\\w+{(.*?)}/$1/g; - - return $paragraph -} - -=back - -=end __PRIVATE__ - -=head1 NOTES - -Compatible with C<latex2e> only. Can not be used with C<latex> v2.09 -or earlier. - -A subclass of C<Pod::Select> so that specific pod sections can be -converted to C<latex> by using the C<select> method. - -Some HTML escapes are missing and many have not been tested. - -=head1 SEE ALSO - -L<Pod::Parser>, L<Pod::Select>, L<pod2latex> - -=head1 AUTHORS - -Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> - -=head1 COPYRIGHT - -Copyright (C) 2000 Tim Jenness. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it -under the same terms as Perl itself. - -=begin __PRIVATE__ - -=head1 REVISION - -$Id: LaTeX.pm,v 1.6 2000/08/21 09:05:03 timj Exp $ - -=end __PRIVATE__ - -=cut diff --git a/contrib/perl5/lib/Pod/Man.pm b/contrib/perl5/lib/Pod/Man.pm deleted file mode 100644 index 3103682..0000000 --- a/contrib/perl5/lib/Pod/Man.pm +++ /dev/null @@ -1,1387 +0,0 @@ -# Pod::Man -- Convert POD data to formatted *roff input. -# $Id: Man.pm,v 1.15 2001/02/10 06:50:22 eagle Exp $ -# -# Copyright 1999, 2000, 2001 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 the pod2man script -# distributed with versions of Perl prior to 5.6, 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 easy -# to subclass. -# -# Perl core hackers, please note that this module is also separately -# maintained outside of the Perl core as part of the podlators. Please send -# me any patches at the address above in addition to sending them to the -# standard Perl mailing lists. - -############################################################################ -# Modules and declarations -############################################################################ - -package Pod::Man; - -require 5.004; - -use Carp qw(carp croak); -use Pod::Parser (); - -use strict; -use subs qw(makespace); -use vars qw(@ISA %ESCAPES $PREAMBLE $VERSION); - -@ISA = qw(Pod::Parser); - -# Don't use the CVS revision as the version, since this module is also in -# Perl core and too many things could munge CVS magic revision strings. -# This number should ideally be the same as the CVS revision in podlators, -# however. -$VERSION = 1.15; - - -############################################################################ -# Preamble and *roff output tables -############################################################################ - -# The following is the static preamble which starts all *roff output we -# generate. It's completely static except for the font to use as a -# fixed-width font, which is designed by @CFONT@, and the left and right -# quotes to use for C<> text, designated by @LQOUTE@ and @RQUOTE@. -# $PREAMBLE should therefore be run through s/\@CFONT\@/<font>/g before -# output. -$PREAMBLE = <<'----END OF PREAMBLE----'; -.de Sh \" Subsection heading -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Ip \" List item -.br -.ie \\n(.$>=3 .ne \\$3 -.el .ne 3 -.IP "\\$1" \\$2 -.. -.de Vb \" Begin verbatim text -.ft @CFONT@ -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R - -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. | will give a -.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used -.\" to do unbreakable dashes and therefore won't be available. \*(C` and -.\" \*(C' expand to `' in nroff, nothing in troff, for use with C<> -.tr \(*W-|\(bv\*(Tr -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` @LQUOTE@ -. ds C' @RQUOTE@ -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" If the F register is turned on, we'll generate index entries on stderr -.\" for titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and -.\" index entries marked with X<> in POD. Of course, you'll have to process -.\" the output yourself in some meaningful fashion. -.if \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it -.\" makes way too many mistakes in technical documents. -.hy 0 -.if n .na -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -.bd B 3 -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -----END OF PREAMBLE---- -#`# for cperl-mode - -# This table is taken nearly verbatim from Tom Christiansen's pod2man. It -# assumes that the standard preamble has already been printed, since that's -# what defines all of the accent marks. Note that some of these are quoted -# with double quotes since they contain embedded single quotes, so use \\ -# uniformly for backslash for readability. -%ESCAPES = ( - 'amp' => '&', # ampersand - 'lt' => '<', # left chevron, less-than - 'gt' => '>', # right chevron, greater-than - 'quot' => '"', # double quote - 'sol' => '/', # solidus (forward slash) - 'verbar' => '|', # vertical bar - - 'Aacute' => "A\\*'", # capital A, acute accent - 'aacute' => "a\\*'", # small a, acute accent - 'Acirc' => 'A\\*^', # capital A, circumflex accent - 'acirc' => 'a\\*^', # small a, circumflex accent - 'AElig' => '\*(AE', # capital AE diphthong (ligature) - 'aelig' => '\*(ae', # small ae diphthong (ligature) - 'Agrave' => "A\\*`", # capital A, grave accent - 'agrave' => "A\\*`", # small a, grave accent - 'Aring' => 'A\\*o', # capital A, ring - 'aring' => 'a\\*o', # small a, ring - 'Atilde' => 'A\\*~', # capital A, tilde - 'atilde' => 'a\\*~', # small a, tilde - 'Auml' => 'A\\*:', # capital A, dieresis or umlaut mark - 'auml' => 'a\\*:', # small a, dieresis or umlaut mark - 'Ccedil' => 'C\\*,', # capital C, cedilla - 'ccedil' => 'c\\*,', # small c, cedilla - 'Eacute' => "E\\*'", # capital E, acute accent - 'eacute' => "e\\*'", # small e, acute accent - 'Ecirc' => 'E\\*^', # capital E, circumflex accent - 'ecirc' => 'e\\*^', # small e, circumflex accent - 'Egrave' => 'E\\*`', # capital E, grave accent - 'egrave' => 'e\\*`', # small e, grave accent - 'ETH' => '\\*(D-', # capital Eth, Icelandic - 'eth' => '\\*(d-', # small eth, Icelandic - 'Euml' => 'E\\*:', # capital E, dieresis or umlaut mark - 'euml' => 'e\\*:', # small e, dieresis or umlaut mark - 'Iacute' => "I\\*'", # capital I, acute accent - 'iacute' => "i\\*'", # small i, acute accent - 'Icirc' => 'I\\*^', # capital I, circumflex accent - 'icirc' => 'i\\*^', # small i, circumflex accent - 'Igrave' => 'I\\*`', # capital I, grave accent - 'igrave' => 'i\\*`', # small i, grave accent - 'Iuml' => 'I\\*:', # capital I, dieresis or umlaut mark - 'iuml' => 'i\\*:', # small i, dieresis or umlaut mark - 'Ntilde' => 'N\*~', # capital N, tilde - 'ntilde' => 'n\*~', # small n, tilde - 'Oacute' => "O\\*'", # capital O, acute accent - 'oacute' => "o\\*'", # small o, acute accent - 'Ocirc' => 'O\\*^', # capital O, circumflex accent - 'ocirc' => 'o\\*^', # small o, circumflex accent - 'Ograve' => 'O\\*`', # capital O, grave accent - 'ograve' => 'o\\*`', # small o, grave accent - 'Oslash' => 'O\\*/', # capital O, slash - 'oslash' => 'o\\*/', # small o, slash - 'Otilde' => 'O\\*~', # capital O, tilde - 'otilde' => 'o\\*~', # small o, tilde - 'Ouml' => 'O\\*:', # capital O, dieresis or umlaut mark - 'ouml' => 'o\\*:', # small o, dieresis or umlaut mark - 'szlig' => '\*8', # small sharp s, German (sz ligature) - 'THORN' => '\\*(Th', # capital THORN, Icelandic - 'thorn' => '\\*(th', # small thorn, Icelandic - 'Uacute' => "U\\*'", # capital U, acute accent - 'uacute' => "u\\*'", # small u, acute accent - 'Ucirc' => 'U\\*^', # capital U, circumflex accent - 'ucirc' => 'u\\*^', # small u, circumflex accent - 'Ugrave' => 'U\\*`', # capital U, grave accent - 'ugrave' => 'u\\*`', # small u, grave accent - 'Uuml' => 'U\\*:', # capital U, dieresis or umlaut mark - 'uuml' => 'u\\*:', # small u, dieresis or umlaut mark - 'Yacute' => "Y\\*'", # capital Y, acute accent - 'yacute' => "y\\*'", # small y, acute accent - 'yuml' => 'y\\*:', # small y, dieresis or umlaut mark -); - - -############################################################################ -# Static helper functions -############################################################################ - -# Protect leading quotes and periods against interpretation as commands. -# Also protect anything starting with a backslash, since it could expand -# or hide something that *roff would interpret as a command. This is -# overkill, but it's much simpler than trying to parse *roff here. -sub protect { - local $_ = shift; - s/^([.\'\\])/\\&$1/mg; - $_; -} - -# Translate a font string into an escape. -sub toescape { (length ($_[0]) > 1 ? '\f(' : '\f') . $_[0] } - - -############################################################################ -# Initialization -############################################################################ - -# Initialize the object. Here, we also process any additional options -# passed to the constructor or set up defaults if none were given. center -# is the centered title, release is the version number, and date is the date -# for the documentation. Note that we can't know what file name we're -# processing due to the architecture of Pod::Parser, so that *has* to either -# be passed to the constructor or set separately with Pod::Man::name(). -sub initialize { - my $self = shift; - - # Figure out the fixed-width font. If user-supplied, make sure that - # they are the right length. - for (qw/fixed fixedbold fixeditalic fixedbolditalic/) { - if (defined $$self{$_}) { - if (length ($$self{$_}) < 1 || length ($$self{$_}) > 2) { - croak qq(roff font should be 1 or 2 chars,) - . qq( not "$$self{$_}"); - } - } else { - $$self{$_} = ''; - } - } - - # Set the default fonts. We can't be sure what fixed bold-italic is - # going to be called, so default to just bold. - $$self{fixed} ||= 'CW'; - $$self{fixedbold} ||= 'CB'; - $$self{fixeditalic} ||= 'CI'; - $$self{fixedbolditalic} ||= 'CB'; - - # Set up a table of font escapes. First number is fixed-width, second - # is bold, third is italic. - $$self{FONTS} = { '000' => '\fR', '001' => '\fI', - '010' => '\fB', '011' => '\f(BI', - '100' => toescape ($$self{fixed}), - '101' => toescape ($$self{fixeditalic}), - '110' => toescape ($$self{fixedbold}), - '111' => toescape ($$self{fixedbolditalic})}; - - # Extra stuff for page titles. - $$self{center} = 'User Contributed Perl Documentation' - unless defined $$self{center}; - $$self{indent} = 4 unless defined $$self{indent}; - - # We used to try first to get the version number from a local binary, - # but we shouldn't need that any more. Get the version from the running - # Perl. Work a little magic to handle subversions correctly under both - # the pre-5.6 and the post-5.6 version numbering schemes. - if (!defined $$self{release}) { - my @version = ($] =~ /^(\d+)\.(\d{3})(\d{0,3})$/); - $version[2] ||= 0; - $version[2] *= 10 ** (3 - length $version[2]); - for (@version) { $_ += 0 } - $$self{release} = 'perl v' . join ('.', @version); - } - - # Double quotes in things that will be quoted. - for (qw/center date release/) { - $$self{$_} =~ s/\"/\"\"/g if $$self{$_}; - } - - # Figure out what quotes we'll be using for C<> text. - $$self{quotes} ||= '"'; - if ($$self{quotes} eq 'none') { - $$self{LQUOTE} = $$self{RQUOTE} = ''; - } elsif (length ($$self{quotes}) == 1) { - $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes}; - } elsif ($$self{quotes} =~ /^(.)(.)$/ - || $$self{quotes} =~ /^(..)(..)$/) { - $$self{LQUOTE} = $1; - $$self{RQUOTE} = $2; - } else { - croak qq(Invalid quote specification "$$self{quotes}"); - } - - # Double the first quote; note that this should not be s///g as two - # double quotes is represented in *roff as three double quotes, not - # four. Weird, I know. - $$self{LQUOTE} =~ s/\"/\"\"/; - $$self{RQUOTE} =~ s/\"/\"\"/; - - $$self{INDENT} = 0; # Current indentation level. - $$self{INDENTS} = []; # Stack of indentations. - $$self{INDEX} = []; # Index keys waiting to be printed. - $$self{ITEMS} = 0; # The number of consecutive =items. - - $self->SUPER::initialize; -} - -# For each document we process, output the preamble first. -sub begin_pod { - my $self = shift; - - # Try to figure out the name and section from the file name. - my $section = $$self{section} || 1; - my $name = $$self{name}; - if (!defined $name) { - $name = $self->input_file; - $section = 3 if (!$$self{section} && $name =~ /\.pm\z/i); - $name =~ s/\.p(od|[lm])\z//i; - if ($section =~ /^1/) { - require File::Basename; - $name = uc File::Basename::basename ($name); - } else { - # Lose everything up to the first of - # */lib/*perl* standard or site_perl module - # */*perl*/lib from -D prefix=/opt/perl - # */*perl*/ random module hierarchy - # which works. Should be fixed to use File::Spec. Also handle - # a leading lib/ since that's what ExtUtils::MakeMaker creates. - for ($name) { - s%//+%/%g; - if ( s%^.*?/lib/[^/]*perl[^/]*/%%si - or s%^.*?/[^/]*perl[^/]*/(?:lib/)?%%si) { - s%^site(_perl)?/%%s; # site and site_perl - s%^(.*-$^O|$^O-.*)/%%so; # arch - s%^\d+\.\d+%%s; # version - } - s%^lib/%%; - s%/%::%g; - } - } - } - - # If $name contains spaces, quote it; this mostly comes up in the case - # of input from stdin. - $name = '"' . $name . '"' if ($name =~ /\s/); - - # Modification date header. Try to use the modification time of our - # input. - if (!defined $$self{date}) { - my $time = (stat $self->input_file)[9] || time; - my ($day, $month, $year) = (localtime $time)[3,4,5]; - $month++; - $year += 1900; - $$self{date} = sprintf ('%4d-%02d-%02d', $year, $month, $day); - } - - # Now, print out the preamble and the title. - local $_ = $PREAMBLE; - s/\@CFONT\@/$$self{fixed}/; - s/\@LQUOTE\@/$$self{LQUOTE}/; - s/\@RQUOTE\@/$$self{RQUOTE}/; - chomp $_; - print { $self->output_handle } <<"----END OF HEADER----"; -.\\" Automatically generated by Pod::Man version $VERSION -.\\" @{[ scalar localtime ]} -.\\" -.\\" Standard preamble: -.\\" ====================================================================== -$_ -.\\" ====================================================================== -.\\" -.IX Title "$name $section" -.TH $name $section "$$self{release}" "$$self{date}" "$$self{center}" -.UC -----END OF HEADER---- -#"# for cperl-mode - - # Initialize a few per-file variables. - $$self{INDENT} = 0; - $$self{NEEDSPACE} = 0; -} - - -############################################################################ -# Core overrides -############################################################################ - -# Called for each command paragraph. Gets the command, the associated -# paragraph, the line number, and a Pod::Paragraph object. Just dispatches -# the command to a method named the same as the command. =cut is handled -# internally by Pod::Parser. -sub command { - my $self = shift; - my $command = shift; - return if $command eq 'pod'; - return if ($$self{EXCLUDE} && $command ne 'end'); - if ($self->can ('cmd_' . $command)) { - $command = 'cmd_' . $command; - $self->$command (@_); - } else { - my ($text, $line, $paragraph) = @_; - my $file; - ($file, $line) = $paragraph->file_line; - $text =~ s/\n+\z//; - $text = " $text" if ($text =~ /^\S/); - warn qq($file:$line: Unknown command paragraph "=$command$text"\n); - return; - } -} - -# Called for a verbatim paragraph. Gets the paragraph, the line number, and -# a Pod::Paragraph object. Rofficate backslashes, untabify, put a -# zero-width character at the beginning of each line to protect against -# commands, and wrap in .Vb/.Ve. -sub verbatim { - my $self = shift; - return if $$self{EXCLUDE}; - local $_ = shift; - return if /^\s+$/; - s/\s+$/\n/; - my $lines = tr/\n/\n/; - 1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me; - s/\\/\\e/g; - s/^(\s*\S)/'\&' . $1/gme; - $self->makespace; - $self->output (".Vb $lines\n$_.Ve\n"); - $$self{NEEDSPACE} = 0; -} - -# Called for a regular text block. Gets the paragraph, the line number, and -# a Pod::Paragraph object. Perform interpolation and output the results. -sub textblock { - my $self = shift; - return if $$self{EXCLUDE}; - $self->output ($_[0]), return if $$self{VERBATIM}; - - # Perform a little magic to collapse multiple L<> references. We'll - # just rewrite the whole thing into actual text at this part, bypassing - # the whole internal sequence parsing thing. - my $text = shift; - $text =~ s{ - (L< # A link of the form L</something>. - / - ( - [:\w]+ # The item has to be a simple word... - (\(\))? # ...or simple function. - ) - > - ( - ,?\s+(and\s+)? # Allow lots of them, conjuncted. - L< - / - ( [:\w]+ ( \(\) )? ) - > - )+ - ) - } { - local $_ = $1; - s{ L< / ( [^>]+ ) > } {$1}xg; - my @items = split /(?:,?\s+(?:and\s+)?)/; - my $string = 'the '; - my $i; - for ($i = 0; $i < @items; $i++) { - $string .= $items[$i]; - $string .= ', ' if @items > 2 && $i != $#items; - $string .= ' ' if @items == 2 && $i == 2; - $string .= 'and ' if ($i == $#items - 1); - } - $string .= ' entries elsewhere in this document'; - $string; - }gex; - - # Parse the tree and output it. collapse knows about references to - # scalars as well as scalars and does the right thing with them. - $text = $self->parse ($text, @_); - $text =~ s/\n\s*$/\n/; - $self->makespace; - $self->output (protect $self->textmapfonts ($text)); - $self->outindex; - $$self{NEEDSPACE} = 1; -} - -# Called for an interior sequence. Takes a Pod::InteriorSequence object and -# returns a reference to a scalar. This scalar is the final formatted text. -# It's returned as a reference so that other interior sequences above us -# know that the text has already been processed. -sub sequence { - my ($self, $seq) = @_; - my $command = $seq->cmd_name; - - # Zero-width characters. - if ($command eq 'Z') { - # Workaround to generate a blessable reference, needed by 5.005. - my $tmp = '\&'; - return bless \ "$tmp", 'Pod::Man::String'; - } - - # C<>, L<>, X<>, and E<> don't apply guesswork to their contents. C<> - # needs some additional special handling. - my $literal = ($command =~ /^[CELX]$/); - $literal++ if $command eq 'C'; - local $_ = $self->collapse ($seq->parse_tree, $literal); - - # Handle E<> escapes. - if ($command eq 'E') { - if (/^\d+$/) { - return bless \ chr ($_), 'Pod::Man::String'; - } elsif (exists $ESCAPES{$_}) { - return bless \ "$ESCAPES{$_}", 'Pod::Man::String'; - } else { - carp "Unknown escape E<$1>"; - return bless \ "E<$_>", 'Pod::Man::String'; - } - } - - # For all the other sequences, empty content produces no output. - return '' if $_ eq ''; - - # Handle formatting sequences. - if ($command eq 'B') { - return bless \ ('\f(BS' . $_ . '\f(BE'), 'Pod::Man::String'; - } elsif ($command eq 'F') { - return bless \ ('\f(IS' . $_ . '\f(IE'), 'Pod::Man::String'; - } elsif ($command eq 'I') { - return bless \ ('\f(IS' . $_ . '\f(IE'), 'Pod::Man::String'; - } elsif ($command eq 'C') { - return bless \ ('\f(FS\*(C`' . $_ . "\\*(C'\\f(FE"), - 'Pod::Man::String'; - } - - # Handle links. - if ($command eq 'L') { - # A bug in lvalue subs in 5.6 requires the temporary variable. - my $tmp = $self->buildlink ($_); - return bless \ "$tmp", 'Pod::Man::String'; - } - - # Whitespace protection replaces whitespace with "\ ". - if ($command eq 'S') { - s/\s+/\\ /g; - return bless \ "$_", 'Pod::Man::String'; - } - - # Add an index entry to the list of ones waiting to be output. - if ($command eq 'X') { push (@{ $$self{INDEX} }, $_); return '' } - - # Anything else is unknown. - carp "Unknown sequence $command<$_>"; -} - - -############################################################################ -# Command paragraphs -############################################################################ - -# All command paragraphs take the paragraph and the line number. - -# First level heading. We can't output .IX in the NAME section due to a bug -# in some versions of catman, so don't output a .IX for that section. .SH -# already uses small caps, so remove any E<> sequences that would cause -# them. -sub cmd_head1 { - my $self = shift; - local $_ = $self->parse (@_); - s/\s+$//; - s/\\s-?\d//g; - s/\s*\n\s*/ /g; - if ($$self{ITEMS} > 1) { - $$self{ITEMS} = 0; - $self->output (".PD\n"); - } - $self->output ($self->switchquotes ('.SH', $self->mapfonts ($_))); - $self->outindex (($_ eq 'NAME') ? () : ('Header', $_)); - $$self{NEEDSPACE} = 0; -} - -# Second level heading. -sub cmd_head2 { - my $self = shift; - local $_ = $self->parse (@_); - s/\s+$//; - s/\s*\n\s*/ /g; - if ($$self{ITEMS} > 1) { - $$self{ITEMS} = 0; - $self->output (".PD\n"); - } - $self->output ($self->switchquotes ('.Sh', $self->mapfonts ($_))); - $self->outindex ('Subsection', $_); - $$self{NEEDSPACE} = 0; -} - -# Third level heading. -sub cmd_head3 { - my $self = shift; - local $_ = $self->parse (@_); - s/\s+$//; - s/\s*\n\s*/ /g; - if ($$self{ITEMS} > 1) { - $$self{ITEMS} = 0; - $self->output (".PD\n"); - } - $self->makespace; - $self->output ($self->switchquotes ('.I', $self->mapfonts ($_))); - $self->outindex ('Subsection', $_); - $$self{NEEDSPACE} = 1; -} - -# Fourth level heading. -sub cmd_head4 { - my $self = shift; - local $_ = $self->parse (@_); - s/\s+$//; - s/\s*\n\s*/ /g; - if ($$self{ITEMS} > 1) { - $$self{ITEMS} = 0; - $self->output (".PD\n"); - } - $self->makespace; - $self->output ($self->textmapfonts ($_) . "\n"); - $self->outindex ('Subsection', $_); - $$self{NEEDSPACE} = 1; -} - -# Start a list. For indents after the first, wrap the outside indent in .RS -# so that hanging paragraph tags will be correct. -sub cmd_over { - my $self = shift; - local $_ = shift; - unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} } - if (@{ $$self{INDENTS} } > 0) { - $self->output (".RS $$self{INDENT}\n"); - } - push (@{ $$self{INDENTS} }, $$self{INDENT}); - $$self{INDENT} = ($_ + 0); -} - -# End a list. If we've closed an embedded indent, we've mangled the hanging -# paragraph indent, so temporarily replace it with .RS and set WEIRDINDENT. -# We'll close that .RS at the next =back or =item. -sub cmd_back { - my $self = shift; - $$self{INDENT} = pop @{ $$self{INDENTS} }; - unless (defined $$self{INDENT}) { - carp "Unmatched =back"; - $$self{INDENT} = 0; - } - if ($$self{WEIRDINDENT}) { - $self->output (".RE\n"); - $$self{WEIRDINDENT} = 0; - } - if (@{ $$self{INDENTS} } > 0) { - $self->output (".RE\n"); - $self->output (".RS $$self{INDENT}\n"); - $$self{WEIRDINDENT} = 1; - } - $$self{NEEDSPACE} = 1; -} - -# An individual list item. Emit an index entry for anything that's -# interesting, but don't emit index entries for things like bullets and -# numbers. rofficate bullets too while we're at it (so for nice output, use -# * for your lists rather than o or . or - or some other thing). Newlines -# in an item title are turned into spaces since *roff can't handle them -# embedded. -sub cmd_item { - my $self = shift; - local $_ = $self->parse (@_); - s/\s+$//; - s/\s*\n\s*/ /g; - my $index; - if (/\w/ && !/^\w[.\)]\s*$/) { - $index = $_; - $index =~ s/^\s*[-*+o.]?(?:\s+|\Z)//; - } - s/^\*(\s|\Z)/\\\(bu$1/; - if ($$self{WEIRDINDENT}) { - $self->output (".RE\n"); - $$self{WEIRDINDENT} = 0; - } - $_ = $self->textmapfonts ($_); - $self->output (".PD 0\n") if ($$self{ITEMS} == 1); - $self->output ($self->switchquotes ('.Ip', $_, $$self{INDENT})); - $self->outindex ($index ? ('Item', $index) : ()); - $$self{NEEDSPACE} = 0; - $$self{ITEMS}++; -} - -# Begin a block for a particular translator. Setting VERBATIM triggers -# special handling in textblock(). -sub cmd_begin { - my $self = shift; - local $_ = shift; - my ($kind) = /^(\S+)/ or return; - if ($kind eq 'man' || $kind eq 'roff') { - $$self{VERBATIM} = 1; - } else { - $$self{EXCLUDE} = 1; - } -} - -# End a block for a particular translator. We assume that all =begin/=end -# pairs are properly closed. -sub cmd_end { - my $self = shift; - $$self{EXCLUDE} = 0; - $$self{VERBATIM} = 0; -} - -# One paragraph for a particular translator. Ignore it unless it's intended -# for man or roff, in which case we output it verbatim. -sub cmd_for { - my $self = shift; - local $_ = shift; - return unless s/^(?:man|roff)\b[ \t]*\n?//; - $self->output ($_); -} - - -############################################################################ -# Link handling -############################################################################ - -# Handle links. We can't actually make real hyperlinks, so this is all to -# figure out what text and formatting we print out. -sub buildlink { - my $self = shift; - local $_ = shift; - - # Smash whitespace in case we were split across multiple lines. - s/\s+/ /g; - - # If we were given any explicit text, just output it. - if (m{ ^ ([^|]+) \| }x) { return $1 } - - # Okay, leading and trailing whitespace isn't important. - s/^\s+//; - s/\s+$//; - - # If the argument looks like a URL, return it verbatim. This only - # handles URLs that use the server syntax. - if (m%^[a-z]+://\S+$%) { return $_ } - - # Default to using the whole content of the link entry as a section - # name. Note that L<manpage/> forces a manpage interpretation, as does - # something looking like L<manpage(section)>. Do the same thing to - # L<manpage(section)> as we would to manpage(section) without the L<>; - # see guesswork(). If we've added italics, don't add the "manpage" - # text; markup is sufficient. - my ($manpage, $section) = ('', $_); - if (/^"\s*(.*?)\s*"$/) { - $section = '"' . $1 . '"'; - } elsif (m{ ^ [-:.\w]+ (?: \( \S+ \) )? $ }x) { - ($manpage, $section) = ($_, ''); - $manpage =~ s/^([^\(]+)\(/'\f(IS' . $1 . '\f(IE\|('/e; - } elsif (m%/%) { - ($manpage, $section) = split (/\s*\/\s*/, $_, 2); - if ($manpage =~ /^[-:.\w]+(?:\(\S+\))?$/) { - $manpage =~ s/^([^\(]+)\(/'\f(IS' . $1 . '\f(IE\|'/e; - } - $section =~ s/^\"\s*//; - $section =~ s/\s*\"$//; - } - if ($manpage && $manpage !~ /\\f\(IS/) { - $manpage = "the $manpage manpage"; - } - - # Now build the actual output text. - my $text = ''; - if (!length ($section) && !length ($manpage)) { - carp "Invalid link $_"; - } elsif (!length ($section)) { - $text = $manpage; - } elsif ($section =~ /^[:\w]+(?:\(\))?/) { - $text .= 'the ' . $section . ' entry'; - $text .= (length $manpage) ? " in $manpage" - : " elsewhere in this document"; - } else { - if ($section !~ /^".*"$/) { $section = '"' . $section . '"' } - $text .= 'the section on ' . $section; - $text .= " in $manpage" if length $manpage; - } - $text; -} - - -############################################################################ -# Escaping and fontification -############################################################################ - -# At this point, we'll have embedded font codes of the form \f(<font>[SE] -# where <font> is one of B, I, or F. Turn those into the right font start -# or end codes. The old pod2man didn't get B<someI<thing> else> right; -# after I<> it switched back to normal text rather than bold. We take care -# of this by using variables as a combined pointer to our current font -# sequence, and set each to the number of current nestings of start tags for -# that font. Use them as a vector to look up what font sequence to use. -# -# \fP changes to the previous font, but only one previous font is kept. We -# don't know what the outside level font is; normally it's R, but if we're -# inside a heading it could be something else. So arrange things so that -# the outside font is always the "previous" font and end with \fP instead of -# \fR. Idea from Zack Weinberg. -sub mapfonts { - my $self = shift; - local $_ = shift; - - my ($fixed, $bold, $italic) = (0, 0, 0); - my %magic = (F => \$fixed, B => \$bold, I => \$italic); - my $last = '\fR'; - s { \\f\((.)(.) } { - my $sequence = ''; - my $f; - if ($last ne '\fR') { $sequence = '\fP' } - ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; - $f = $$self{FONTS}{($fixed && 1) . ($bold && 1) . ($italic && 1)}; - if ($f eq $last) { - ''; - } else { - if ($f ne '\fR') { $sequence .= $f } - $last = $f; - $sequence; - } - }gxe; - $_; -} - -# Unfortunately, there is a bug in Solaris 2.6 nroff (not present in GNU -# groff) where the sequence \fB\fP\f(CW\fP leaves the font set to B rather -# than R, presumably because \f(CW doesn't actually do a font change. To -# work around this, use a separate textmapfonts for text blocks where the -# default font is always R and only use the smart mapfonts for headings. -sub textmapfonts { - my $self = shift; - local $_ = shift; - - my ($fixed, $bold, $italic) = (0, 0, 0); - my %magic = (F => \$fixed, B => \$bold, I => \$italic); - s { \\f\((.)(.) } { - ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; - $$self{FONTS}{($fixed && 1) . ($bold && 1) . ($italic && 1)}; - }gxe; - $_; -} - - -############################################################################ -# *roff-specific parsing -############################################################################ - -# Called instead of parse_text, calls parse_text with the right flags. -sub parse { - my $self = shift; - $self->parse_text ({ -expand_seq => 'sequence', - -expand_ptree => 'collapse' }, @_); -} - -# Takes a parse tree and a flag saying whether or not to treat it as literal -# text (not call guesswork on it), and returns the concatenation of all of -# the text strings in that parse tree. If the literal flag isn't true, -# guesswork() will be called on all plain scalars in the parse tree. -# Otherwise, just escape backslashes in the normal case. If collapse is -# being called on a C<> sequence, literal is set to 2, and we do some -# additional cleanup. Assumes that everything in the parse tree is either a -# scalar or a reference to a scalar. -sub collapse { - my ($self, $ptree, $literal) = @_; - if ($literal) { - return join ('', map { - if (ref $_) { - $$_; - } else { - s/\\/\\e/g; - s/-/\\-/g if $literal > 1; - s/__/_\\|_/g if $literal > 1; - $_; - } - } $ptree->children); - } else { - return join ('', map { - ref ($_) ? $$_ : $self->guesswork ($_) - } $ptree->children); - } -} - -# Takes a text block to perform guesswork on; this is guaranteed not to -# contain any interior sequences. Returns the text block with remapping -# done. -sub guesswork { - my $self = shift; - local $_ = shift; - - # rofficate backslashes. - s/\\/\\e/g; - - # Ensure double underbars have a tiny space between them. - s/__/_\\|_/g; - - # Make all caps a little smaller. Be careful here, since we don't want - # to make @ARGV into small caps, nor do we want to fix the MIME in - # MIME-Version, since it looks weird with the full-height V. - s{ - ( ^ | [\s\(\"\'\`\[\{<>] ) - ( [A-Z] [A-Z] [/A-Z+:\d_\$&-]* ) - (?: (?= [\s>\}\]\)\'\".?!,;:] | -- ) | $ ) - } { $1 . '\s-1' . $2 . '\s0' }egx; - - # Turn PI into a pretty pi. - s{ (?: \\s-1 | \b ) PI (?: \\s0 | \b ) } {\\*\(PI}gx; - - # Italize functions in the form func(). - s{ - \b - ( - [:\w]+ (?:\\s-1)? \(\) - ) - } { '\f(IS' . $1 . '\f(IE' }egx; - - # func(n) is a reference to a manual page. Make it \fIfunc\fR\|(n). - s{ - \b - (\w[-:.\w]+ (?:\\s-1)?) - ( - \( [^\)] \) - ) - } { '\f(IS' . $1 . '\f(IE\|' . $2 }egx; - - # Convert simple Perl variable references to a fixed-width font. - s{ - ( \s+ ) - ( [\$\@%] [\w:]+ ) - (?! \( ) - } { $1 . '\f(FS' . $2 . '\f(FE'}egx; - - # Translate -- into a real em dash if it's used like one and fix up - # dashes, but keep hyphens hyphens. - s{ (\G|^|.) (-+) (\b|.) } { - my ($pre, $dash, $post) = ($1, $2, $3); - if (length ($dash) == 1) { - ($pre =~ /[a-zA-Z]/) ? "$pre-$post" : "$pre\\-$post"; - } elsif (length ($dash) == 2 - && ((!$pre && !$post) - || ($pre =~ /\w/ && !$post) - || ($pre eq ' ' && $post eq ' ') - || ($pre eq '=' && $post ne '=') - || ($pre ne '=' && $post eq '='))) { - "$pre\\*(--$post"; - } else { - $pre . ('\-' x length $dash) . $post; - } - }egxs; - - # Fix up double quotes. - s{ \" ([^\"]+) \" } { '\*(L"' . $1 . '\*(R"' }egx; - - # Make C++ into \*(C+, which is a squinched version. - s{ \b C\+\+ } {\\*\(C+}gx; - - # All done. - $_; -} - - -############################################################################ -# Output formatting -############################################################################ - -# Make vertical whitespace. -sub makespace { - my $self = shift; - $self->output (".PD\n") if ($$self{ITEMS} > 1); - $$self{ITEMS} = 0; - $self->output ($$self{INDENT} > 0 ? ".Sp\n" : ".PP\n") - if $$self{NEEDSPACE}; -} - -# Output any pending index entries, and optionally an index entry given as -# an argument. Support multiple index entries in X<> separated by slashes, -# and strip special escapes from index entries. -sub outindex { - my ($self, $section, $index) = @_; - my @entries = map { split m%\s*/\s*% } @{ $$self{INDEX} }; - return unless ($section || @entries); - $$self{INDEX} = []; - my $output; - if (@entries) { - my $output = '.IX Xref "' - . join (' ', map { s/\"/\"\"/; $_ } @entries) - . '"' . "\n"; - } - if ($section) { - $index =~ s/\"/\"\"/; - $index =~ s/\\-/-/g; - $index =~ s/\\(?:s-?\d|.\(..|.)//g; - $output .= ".IX $section " . '"' . $index . '"' . "\n"; - } - $self->output ($output); -} - -# Output text to the output device. -sub output { print { $_[0]->output_handle } $_[1] } - -# Given a command and a single argument that may or may not contain double -# quotes, handle double-quote formatting for it. If there are no double -# quotes, just return the command followed by the argument in double quotes. -# If there are double quotes, use an if statement to test for nroff, and for -# nroff output the command followed by the argument in double quotes with -# embedded double quotes doubled. For other formatters, remap paired double -# quotes to LQUOTE and RQUOTE. -sub switchquotes { - my $self = shift; - my $command = shift; - local $_ = shift; - my $extra = shift; - s/\\\*\([LR]\"/\"/g; - - # We also have to deal with \*C` and \*C', which are used to add the - # quotes around C<> text, since they may expand to " and if they do this - # confuses the .SH macros and the like no end. Expand them ourselves. - # If $extra is set, we're dealing with =item, which in most nroff macro - # sets requires an extra level of quoting of double quotes. - my $c_is_quote = ($$self{LQUOTE} =~ /\"/) || ($$self{RQUOTE} =~ /\"/); - if (/\"/ || ($c_is_quote && /\\\*\(C[\'\`]/)) { - s/\"/\"\"/g; - my $troff = $_; - $troff =~ s/\"\"([^\"]*)\"\"/\`\`$1\'\'/g; - s/\\\*\(C\`/$$self{LQUOTE}/g; - s/\\\*\(C\'/$$self{RQUOTE}/g; - $troff =~ s/\\\*\(C[\'\`]//g; - s/\"/\"\"/g if $extra; - $troff =~ s/\"/\"\"/g if $extra; - $_ = qq("$_") . ($extra ? " $extra" : ''); - $troff = qq("$troff") . ($extra ? " $extra" : ''); - return ".if n $command $_\n.el $command $troff\n"; - } else { - $_ = qq("$_") . ($extra ? " $extra" : ''); - return "$command $_\n"; - } -} - -__END__ - -.\" These are some extra bits of roff that I don't want to lose track of -.\" but that have been removed from the preamble to make it a bit shorter -.\" since they're not currently being used. They're accents and special -.\" characters we don't currently have escapes for. -.if n \{\ -. ds ? ? -. ds ! ! -. ds q -.\} -.if t \{\ -. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' -. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' -. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' -.\} -.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] -.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' -.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' -.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] -.ds oe o\h'-(\w'o'u*4/10)'e -.ds Oe O\h'-(\w'O'u*4/10)'E -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds v \h'-1'\o'\(aa\(ga' -. ds _ \h'-1'^ -. ds . \h'-1'. -. ds 3 3 -. ds oe oe -. ds Oe OE -.\} - -############################################################################ -# Documentation -############################################################################ - -=head1 NAME - -Pod::Man - Convert POD data to formatted *roff input - -=head1 SYNOPSIS - - use Pod::Man; - my $parser = Pod::Man->new (release => $VERSION, section => 8); - - # Read POD from STDIN and write to STDOUT. - $parser->parse_from_filehandle; - - # Read POD from file.pod and write to file.1. - $parser->parse_from_file ('file.pod', 'file.1'); - -=head1 DESCRIPTION - -Pod::Man is a module to convert documentation in the POD format (the -preferred language for documenting Perl) into *roff input using the man -macro set. The resulting *roff code is suitable for display on a terminal -using nroff(1), normally via man(1), or printing using troff(1). It is -conventionally invoked using the driver script B<pod2man>, but it can also -be used directly. - -As a derived class from Pod::Parser, Pod::Man supports the same methods and -interfaces. See L<Pod::Parser> for all the details; briefly, one creates a -new parser with C<Pod::Man-E<gt>new()> and then calls either -parse_from_filehandle() or parse_from_file(). - -new() can take options, in the form of key/value pairs that control the -behavior of the parser. See below for details. - -If no options are given, Pod::Man uses the name of the input file with any -trailing C<.pod>, C<.pm>, or C<.pl> stripped as the man page title, to -section 1 unless the file ended in C<.pm> in which case it defaults to -section 3, to a centered title of "User Contributed Perl Documentation", to -a centered footer of the Perl version it is run with, and to a left-hand -footer of the modification date of its input (or the current date if given -STDIN for input). - -Pod::Man assumes that your *roff formatters have a fixed-width font named -CW. If yours is called something else (like CR), use the C<fixed> option to -specify it. This generally only matters for troff output for printing. -Similarly, you can set the fonts used for bold, italic, and bold italic -fixed-width output. - -Besides the obvious pod conversions, Pod::Man also takes care of formatting -func(), func(n), and simple variable references like $foo or @bar so you -don't have to use code escapes for them; complex expressions like -C<$fred{'stuff'}> will still need to be escaped, though. It also translates -dashes that aren't used as hyphens into en dashes, makes long dashes--like -this--into proper em dashes, fixes "paired quotes," makes C++ and PI look -right, puts a little space between double underbars, makes ALLCAPS a teeny -bit smaller in troff(1), and escapes stuff that *roff treats as special so -that you don't have to. - -The recognized options to new() are as follows. All options take a single -argument. - -=over 4 - -=item center - -Sets the centered page header to use instead of "User Contributed Perl -Documentation". - -=item date - -Sets the left-hand footer. By default, the modification date of the input -file will be used, or the current date if stat() can't find that file (the -case if the input is from STDIN), and the date will be formatted as -YYYY-MM-DD. - -=item fixed - -The fixed-width font to use for vertabim text and code. Defaults to CW. -Some systems may want CR instead. Only matters for troff(1) output. - -=item fixedbold - -Bold version of the fixed-width font. Defaults to CB. Only matters for -troff(1) output. - -=item fixeditalic - -Italic version of the fixed-width font (actually, something of a misnomer, -since most fixed-width fonts only have an oblique version, not an italic -version). Defaults to CI. Only matters for troff(1) output. - -=item fixedbolditalic - -Bold italic (probably actually oblique) version of the fixed-width font. -Pod::Man doesn't assume you have this, and defaults to CB. Some systems -(such as Solaris) have this font available as CX. Only matters for troff(1) -output. - -=item quotes - -Sets the quote marks used to surround CE<lt>> text. If the value is a -single character, it is used as both the left and right quote; if it is two -characters, the first character is used as the left quote and the second as -the right quoted; and if it is four characters, the first two are used as -the left quote and the second two as the right quote. - -This may also be set to the special value C<none>, in which case no quote -marks are added around CE<lt>> text (but the font is still changed for troff -output). - -=item release - -Set the centered footer. By default, this is the version of Perl you run -Pod::Man under. Note that some system an macro sets assume that the -centered footer will be a modification date and will prepend something like -"Last modified: "; if this is the case, you may want to set C<release> to -the last modified date and C<date> to the version number. - -=item section - -Set the section for the C<.TH> macro. The standard section numbering -convention is to use 1 for user commands, 2 for system calls, 3 for -functions, 4 for devices, 5 for file formats, 6 for games, 7 for -miscellaneous information, and 8 for administrator commands. There is a lot -of variation here, however; some systems (like Solaris) use 4 for file -formats, 5 for miscellaneous information, and 7 for devices. Still others -use 1m instead of 8, or some mix of both. About the only section numbers -that are reliably consistent are 1, 2, and 3. - -By default, section 1 will be used unless the file ends in .pm in which case -section 3 will be selected. - -=back - -The standard Pod::Parser method parse_from_filehandle() takes up to two -arguments, the first being the file handle to read POD from and the second -being the file handle to write the formatted output to. The first defaults -to STDIN if not given, and the second defaults to STDOUT. The method -parse_from_file() is almost identical, except that its two arguments are the -input and output disk files instead. See L<Pod::Parser> for the specific -details. - -=head1 DIAGNOSTICS - -=over 4 - -=item roff font should be 1 or 2 chars, not "%s" - -(F) You specified a *roff font (using C<fixed>, C<fixedbold>, etc.) that -wasn't either one or two characters. Pod::Man doesn't support *roff fonts -longer than two characters, although some *roff extensions do (the canonical -versions of nroff(1) and troff(1) don't either). - -=item Invalid link %s - -(W) The POD source contained a C<LE<lt>E<gt>> sequence that Pod::Man was -unable to parse. You should never see this error message; it probably -indicates a bug in Pod::Man. - -=item Invalid quote specification "%s" - -(F) The quote specification given (the quotes option to the constructor) was -invalid. A quote specification must be one, two, or four characters long. - -=item %s:%d: Unknown command paragraph "%s". - -(W) The POD source contained a non-standard command paragraph (something of -the form C<=command args>) that Pod::Man didn't know about. It was ignored. - -=item Unknown escape EE<lt>%sE<gt> - -(W) The POD source contained an C<EE<lt>E<gt>> escape that Pod::Man didn't -know about. C<EE<lt>%sE<gt>> was printed verbatim in the output. - -=item Unknown sequence %s - -(W) The POD source contained a non-standard interior sequence (something of -the form C<XE<lt>E<gt>>) that Pod::Man didn't know about. It was ignored. - -=item %s: Unknown command paragraph "%s" on line %d. - -(W) The POD source contained a non-standard command paragraph (something of -the form C<=command args>) that Pod::Man didn't know about. It was ignored. - -=item Unmatched =back - -(W) Pod::Man encountered a C<=back> command that didn't correspond to an -C<=over> command. - -=back - -=head1 BUGS - -The lint-like features and strict POD format checking done by B<pod2man> are -not yet implemented and should be, along with the corresponding C<lax> -option. - -The NAME section should be recognized specially and index entries emitted -for everything in that section. This would have to be deferred until the -next section, since extraneous things in NAME tends to confuse various man -page processors. - -The handling of hyphens, en dashes, and em dashes is somewhat fragile, and -one may get the wrong one under some circumstances. This should only matter -for troff(1) output. - -When and whether to use small caps is somewhat tricky, and Pod::Man doesn't -necessarily get it right. - -Pod::Man doesn't handle font names longer than two characters. Neither do -most troff(1) implementations, but GNU troff does as an extension. It would -be nice to support as an option for those who want to use it. - -The preamble added to each output file is rather verbose, and most of it is -only necessary in the presence of EE<lt>E<gt> escapes for non-ASCII -characters. It would ideally be nice if all of those definitions were only -output if needed, perhaps on the fly as the characters are used. - -Some of the automagic applied to file names assumes Unix directory -separators. - -Pod::Man is excessively slow. - -=head1 SEE ALSO - -L<Pod::Parser|Pod::Parser>, perlpod(1), pod2man(1), nroff(1), troff(1), -man(1), man(7) - -Ossanna, Joseph F., and Brian W. Kernighan. "Troff User's Manual," -Computing Science Technical Report No. 54, AT&T Bell Laboratories. This is -the best documentation of standard nroff(1) and troff(1). At the time of -this writing, it's available at http://www.cs.bell-labs.com/cm/cs/cstr.html. - -The man page documenting the man macro set may be man(5) instead of man(7) -on your system. Also, please see pod2man(1) for extensive documentation on -writing manual pages if you've not done it before and aren't familiar with -the conventions. - -=head1 AUTHOR - -Russ Allbery E<lt>rra@stanford.eduE<gt>, based I<very> heavily on the -original B<pod2man> by Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>. - -=cut diff --git a/contrib/perl5/lib/Pod/ParseUtils.pm b/contrib/perl5/lib/Pod/ParseUtils.pm deleted file mode 100644 index 7d994c7..0000000 --- a/contrib/perl5/lib/Pod/ParseUtils.pm +++ /dev/null @@ -1,851 +0,0 @@ -############################################################################# -# 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 vars qw($VERSION); -$VERSION = 0.22; ## 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<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 undef 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 deprected, 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) = (undef,'','',''); - - $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 undef; - } - - ## 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 funtion... - my $page_rx = '[\w.]+(?:::[\w.]+)*(?:[(](?:\d\w*|)[)]|)'; - # page name only - if(m!^($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'; - } - # alttext and page - elsif(m!^(.*?)\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'; - } - # page and "section" - elsif(m!^($page_rx)\s*/\s*"(.+)"$!o) { - ($page, $node) = ($1, $2); - $type = 'section'; - } - # page and item - elsif(m!^($page_rx)\s*/\s*(.+)$!o) { - ($page, $node) = ($1, $2); - $type = 'item'; - } - # only "section" - elsif(m!^/?"(.+)"$!) { - $node = $1; - $type = 'section'; - } - # only item - elsif(m!^\s*/(.+)$!) { - $node = $1; - $type = 'item'; - } - # non-standard: Hyperlink - elsif(m!^((?:http|ftp|mailto|news):.+)$!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); - } - # nonstandard: alttext and hyperlink - elsif(m!^(.*?)\s*[|]\s*((?:http|ftp|mailto|news):.+)$!) { - ($alttext, $node) = ($1,$2); - $type = 'hyperlink'; - } - # 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($node =~ m:[|/]:) { - $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 ? '' : - $type eq 'item' ? "the $section entry" : - "the section on $section" ) . - ($page ? ($section ? ' in ':'') . "the $page$page_ext manpage" : - ' elsewhere in this document'); - } - # 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 ? '' : - $type eq 'item' ? "the Q<$section> entry" : - "the section on Q<$section>" ) . - ($page ? ($section ? ' in ':'') . "the P<$page>$page_ext manpage" : - ' elsewhere in this document'); - } -} - -=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): - - the +perl+ manpage - the *$|* entry in the +perlvar+ manpage - the section on *OPTIONS* in the +perldoc+ manpage - the section on *DESCRIPTION* elsewhere in this document - -=cut - -# The complete link's text -sub text { - $_[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(); - } - $_[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(); - } - $_[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(); - } - $_[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(); - $text =~ s/\|/E<verbar>/g; - $text =~ 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"; - } - $link; -} - -sub _invalid_link { - my ($msg) = @_; - # this sets @_ - #eval { die "$msg\n" }; - #chomp $@; - $@ = $msg; # this seems to work, too! - undef; -} - -#----------------------------------------------------------------------------- -# 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 $_; - } - } - undef; -} - -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 arry) 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 - } - } - undef; -} - -=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 - -Marek Rouchal E<lt>marek@saftsack.fs.uni-bayreuth.deE<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. - -=head1 SEE ALSO - -L<pod2man>, L<pod2roff>, L<Pod::Parser>, L<Pod::Checker>, -L<pod2html> - -=cut - -1; diff --git a/contrib/perl5/lib/Pod/Parser.pm b/contrib/perl5/lib/Pod/Parser.pm deleted file mode 100644 index 6782519..0000000 --- a/contrib/perl5/lib/Pod/Parser.pm +++ /dev/null @@ -1,1768 +0,0 @@ -############################################################################# -# 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 vars qw($VERSION); -$VERSION = 1.13; ## 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<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 preprocesssing 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 intepret 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 -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 vars qw(@ISA); -use strict; -#use diagnostics; -use Pod::InputObjects; -use Carp; -use Exporter; -BEGIN { - if ($] < 5.6) { - require Symbol; - import Symbol; - } -} -@ISA = qw(Exporter); - -## These "variables" are used as local "glob aliases" for performance -use vars qw(%myData %myOpts @input_stack); - -############################################################################# - -=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 = shift; - my $class = ref($this) || $this; - ## Any remaining arguments are treated as initial values for the - ## hash that is used to represent this object. - my %params = @_; - 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 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 curresponding 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 ($self, $iseq) = @_; - my $args = join("", $iseq->parse_tree->children); - return $self->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]<(?:<+\s)?)/; - while ( @tokens ) { - $_ = shift @tokens; - ## Look for the beginning of a sequence - if ( /^([A-Z])(<(?:<+\s)?)$/ ) { - ## Push a new sequence onto the stack of those "in-progress" - ($cmd, $ldelim) = ($1, $2); - $seq = Pod::InteriorSequence->new( - -name => $cmd, - -ldelim => $ldelim, -rdelim => '', - -file => $file, -line => $line - ); - $ldelim =~ s/\s+$//, ($rdelim = $ldelim) =~ tr/</>/; - (@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 - ## dont 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 - $cmd = (@seq_stack > 1) ? $seq_stack[-1]->name : ''; - $ldelim = (@seq_stack > 1) ? $seq_stack[-1]->ldelim : ''; - $ldelim =~ s/\s+$//, ($rdelim = $ldelim) =~ tr/</>/; - } - } - elsif (length) { - ## In the middle of a sequence, append this text to it, and - ## dont 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 += tr/\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 warn($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 isnt in one of the selected sections - if (exists $myData{_SELECTED_SECTIONS}) { - $self->is_selected($text) or return ($myData{_CUTTING} = 1); - } - - ## If we havent 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; - ## If this is a "cut" directive then we dont 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 (length $cmd) { - ## A command paragraph - $self->command($cmd, $text, $line_num, $pod_para); - } - elsif ($text =~ /^\s+/) { - ## Indented text - must be a verbatim paragraph - $self->verbatim($text, $line_num, $pod_para); - } - else { - ## Looks like an ordinary block of text - $self->textblock($text, $line_num, $pod_para); - } - 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)); - $_ = $paragraph; ## save previous contents - - 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 isnt, then keep iterating until it is. - next unless (($textline =~ /^([^\S\r\n]*)[\r\n]*$/) - && (length $paragraph)); - - ## Issue a warning about any non-empty blank lines - if (length($1) > 0 and $myOpts{'-warnings'} and ! $myData{_CUTTING}) { - my $errorsub = $self->errorsub(); - my $file = $self->input_file(); - my $errmsg = "*** WARNING: line containing nothing but whitespace". - " in paragraph at line $nlines in file $file\n"; - (ref $errorsub) and &{$errorsub}($errmsg) - or (defined $errorsub) and $self->$errorsub($errmsg) - or warn($errmsg); - } - - ## Now process the paragraph - parse_paragraph($self, $paragraph, ($nlines - $plines) + 1); - $paragraph = ''; - $plines = 0; - } - ## Dont 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. - -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. - -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) = (gensym, gensym) if ($] < 5.6); - my ($close_input, $close_output) = (0, 0); - local *myData = $self; - local $_; - - ## Is $infile a filename or a (possibly implied) filehandle - $infile = '-' unless ((defined $infile) && (length $infile)); - if (($infile eq '-') || ($infile =~ /^<&(STDIN|0)$/i)) { - ## Not a filename, just a string implying STDIN - $myData{_INFILE} = "<standard input>"; - $in_fh = \*STDIN; - } - elsif (ref $infile) { - ## 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; - } - 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 - ## - unless ((defined $outfile) && (length $outfile)) { - (defined $myData{_TOP_STREAM}) && ($out_fh = $myData{_OUTPUT}) - || ($outfile = '-'); - } - ## Is $outfile a filename or a (possibly implied) filehandle - if ((defined $outfile) && (length $outfile)) { - if (($outfile eq '-') || ($outfile =~ /^>&?(?:STDOUT|1)$/i)) { - ## Not a filename, just a string implying STDOUT - $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; - } - elsif (ref $outfile) { - ## 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; - } - 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<warn> -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 warn($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<warn> 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(); - - ## Dont 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 -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 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 - -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> - -=cut - -1; diff --git a/contrib/perl5/lib/Pod/Plainer.pm b/contrib/perl5/lib/Pod/Plainer.pm deleted file mode 100644 index 373e8d0..0000000 --- a/contrib/perl5/lib/Pod/Plainer.pm +++ /dev/null @@ -1,69 +0,0 @@ -package Pod::Plainer; -use strict; -use Pod::Parser; -our @ISA = qw(Pod::Parser); -our $VERSION = '0.01'; - -our %E = qw( < lt > gt ); - -sub escape_ltgt { - (undef, my $text) = @_; - $text =~ s/([<>])/E<$E{$1}>/g; - $text -} - -sub simple_delimiters { - (undef, my $seq) = @_; - $seq -> left_delimiter( '<' ); - $seq -> right_delimiter( '>' ); - $seq; -} - -sub textblock { - my($parser,$text,$line) = @_; - print {$parser->output_handle()} - $parser->parse_text( - { -expand_text => q(escape_ltgt), - -expand_seq => q(simple_delimiters) }, - $text, $line ) -> raw_text(); -} - -1; - -__END__ - -=head1 NAME - -Pod::Plainer - Perl extension for converting Pod to old style Pod. - -=head1 SYNOPSIS - - use Pod::Plainer; - - my $parser = Pod::Plainer -> new (); - $parser -> parse_from_filehandle(\*STDIN); - -=head1 DESCRIPTION - -Pod::Plainer uses Pod::Parser which takes Pod with the (new) -'CE<lt>E<lt> .. E<gt>E<gt>' constructs -and returns the old(er) style with just 'CE<lt>E<gt>'; -'<' and '>' are replaced by 'EE<lt>ltE<gt>' and 'EE<lt>gtE<gt>'. - -This can be used to pre-process Pod before using tools which do not -recognise the new style Pods. - -=head2 EXPORT - -None by default. - -=head1 AUTHOR - -Robin Barker, rmb1@cise.npl.co.uk - -=head1 SEE ALSO - -See L<Pod::Parser>. - -=cut - diff --git a/contrib/perl5/lib/Pod/Select.pm b/contrib/perl5/lib/Pod/Select.pm deleted file mode 100644 index e7c820f..0000000 --- a/contrib/perl5/lib/Pod/Select.pm +++ /dev/null @@ -1,751 +0,0 @@ -############################################################################# -# Pod/Select.pm -- function to select portions of 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::Select; - -use vars qw($VERSION); -$VERSION = 1.13; ## Current version of this package -require 5.005; ## requires this Perl version or later - -############################################################################# - -=head1 NAME - -Pod::Select, podselect() - extract selected sections of POD from input - -=head1 SYNOPSIS - - use Pod::Select; - - ## Select all the POD sections for each file in @filelist - ## and print the result on standard output. - podselect(@filelist); - - ## Same as above, but write to tmp.out - podselect({-output => "tmp.out"}, @filelist): - - ## Select from the given filelist, only those POD sections that are - ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS. - podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist): - - ## Select the "DESCRIPTION" section of the PODs from STDIN and write - ## the result to STDERR. - podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN); - -or - - use Pod::Select; - - ## Create a parser object for selecting POD sections from the input - $parser = new Pod::Select(); - - ## Select all the POD sections for each file in @filelist - ## and print the result to tmp.out. - $parser->parse_from_file("<&STDIN", "tmp.out"); - - ## Select from the given filelist, only those POD sections that are - ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS. - $parser->select("NAME|SYNOPSIS", "OPTIONS"); - for (@filelist) { $parser->parse_from_file($_); } - - ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from - ## STDIN and write the result to STDERR. - $parser->select("DESCRIPTION"); - $parser->add_selection("SEE ALSO"); - $parser->parse_from_filehandle(\*STDIN, \*STDERR); - -=head1 REQUIRES - -perl5.005, Pod::Parser, Exporter, Carp - -=head1 EXPORTS - -podselect() - -=head1 DESCRIPTION - -B<podselect()> is a function which will extract specified sections of -pod documentation from an input stream. This ability is provided by the -B<Pod::Select> module which is a subclass of B<Pod::Parser>. -B<Pod::Select> provides a method named B<select()> to specify the set of -POD sections to select for processing/printing. B<podselect()> merely -creates a B<Pod::Select> object and then invokes the B<podselect()> -followed by B<parse_from_file()>. - -=head1 SECTION SPECIFICATIONS - -B<podselect()> and B<Pod::Select::select()> may be given one or more -"section specifications" to restrict the text processed to only the -desired set of sections and their corresponding subsections. A section -specification is a string containing one or more Perl-style regular -expressions separated by forward slashes ("/"). If you need to use a -forward slash literally within a section title you can escape it with a -backslash ("\/"). - -The formal syntax of a section specification is: - -=over 4 - -=item * - -I<head1-title-regex>/I<head2-title-regex>/... - -=back - -Any omitted or empty regular expressions will default to ".*". -Please note that each regular expression given is implicitly -anchored by adding "^" and "$" to the beginning and end. Also, if a -given regular expression starts with a "!" character, then the -expression is I<negated> (so C<!foo> would match anything I<except> -C<foo>). - -Some example section specifications follow. - -=over 4 - -=item * - -Match the C<NAME> and C<SYNOPSIS> sections and all of their subsections: - -C<NAME|SYNOPSIS> - -=item * - -Match only the C<Question> and C<Answer> subsections of the C<DESCRIPTION> -section: - -C<DESCRIPTION/Question|Answer> - -=item * - -Match the C<Comments> subsection of I<all> sections: - -C</Comments> - -=item * - -Match all subsections of C<DESCRIPTION> I<except> for C<Comments>: - -C<DESCRIPTION/!Comments> - -=item * - -Match the C<DESCRIPTION> section but do I<not> match any of its subsections: - -C<DESCRIPTION/!.+> - -=item * - -Match all top level sections but none of their subsections: - -C</!.+> - -=back - -=begin _NOT_IMPLEMENTED_ - -=head1 RANGE SPECIFICATIONS - -B<podselect()> and B<Pod::Select::select()> may be given one or more -"range specifications" to restrict the text processed to only the -desired ranges of paragraphs in the desired set of sections. A range -specification is a string containing a single Perl-style regular -expression (a regex), or else two Perl-style regular expressions -(regexs) separated by a ".." (Perl's "range" operator is ".."). -The regexs in a range specification are delimited by forward slashes -("/"). If you need to use a forward slash literally within a regex you -can escape it with a backslash ("\/"). - -The formal syntax of a range specification is: - -=over 4 - -=item * - -/I<start-range-regex>/[../I<end-range-regex>/] - -=back - -Where each the item inside square brackets (the ".." followed by the -end-range-regex) is optional. Each "range-regex" is of the form: - - =cmd-expr text-expr - -Where I<cmd-expr> is intended to match the name of one or more POD -commands, and I<text-expr> is intended to match the paragraph text for -the command. If a range-regex is supposed to match a POD command, then -the first character of the regex (the one after the initial '/') -absolutely I<must> be an single '=' character; it may not be anything -else (not even a regex meta-character) if it is supposed to match -against the name of a POD command. - -If no I<=cmd-expr> is given then the text-expr will be matched against -plain textblocks unless it is preceded by a space, in which case it is -matched against verbatim text-blocks. If no I<text-expr> is given then -only the command-portion of the paragraph is matched against. - -Note that these two expressions are each implicitly anchored. This -means that when matching against the command-name, there will be an -implicit '^' and '$' around the given I<=cmd-expr>; and when matching -against the paragraph text there will be an implicit '\A' and '\Z' -around the given I<text-expr>. - -Unlike with section-specs, the '!' character does I<not> have any special -meaning (negation or otherwise) at the beginning of a range-spec! - -Some example range specifications follow. - -=over 4 - -=item -Match all C<=for html> paragraphs: - -C</=for html/> - -=item -Match all paragraphs between C<=begin html> and C<=end html> -(note that this will I<not> work correctly if such sections -are nested): - -C</=begin html/../=end html/> - -=item -Match all paragraphs between the given C<=item> name until the end of the -current section: - -C</=item mine/../=head\d/> - -=item -Match all paragraphs between the given C<=item> until the next item, or -until the end of the itemized list (note that this will I<not> work as -desired if the item contains an itemized list nested within it): - -C</=item mine/../=(item|back)/> - -=back - -=end _NOT_IMPLEMENTED_ - -=cut - -############################################################################# - -use strict; -#use diagnostics; -use Carp; -use Pod::Parser 1.04; -use vars qw(@ISA @EXPORT $MAX_HEADING_LEVEL); - -@ISA = qw(Pod::Parser); -@EXPORT = qw(&podselect); - -## Maximum number of heading levels supported for '=headN' directives -*MAX_HEADING_LEVEL = \3; - -############################################################################# - -=head1 OBJECT METHODS - -The following methods are provided in this module. Each one takes a -reference to the object itself as an implicit first parameter. - -=cut - -##--------------------------------------------------------------------------- - -## =begin _PRIVATE_ -## -## =head1 B<_init_headings()> -## -## Initialize the current set of active section headings. -## -## =cut -## -## =end _PRIVATE_ - -use vars qw(%myData @section_headings); - -sub _init_headings { - my $self = shift; - local *myData = $self; - - ## Initialize current section heading titles if necessary - unless (defined $myData{_SECTION_HEADINGS}) { - local *section_headings = $myData{_SECTION_HEADINGS} = []; - for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { - $section_headings[$i] = ''; - } - } -} - -##--------------------------------------------------------------------------- - -=head1 B<curr_headings()> - - ($head1, $head2, $head3, ...) = $parser->curr_headings(); - $head1 = $parser->curr_headings(1); - -This method returns a list of the currently active section headings and -subheadings in the document being parsed. The list of headings returned -corresponds to the most recently parsed paragraph of the input. - -If an argument is given, it must correspond to the desired section -heading number, in which case only the specified section heading is -returned. If there is no current section heading at the specified -level, then C<undef> is returned. - -=cut - -sub curr_headings { - my $self = shift; - $self->_init_headings() unless (defined $self->{_SECTION_HEADINGS}); - my @headings = @{ $self->{_SECTION_HEADINGS} }; - return (@_ > 0 and $_[0] =~ /^\d+$/) ? $headings[$_[0] - 1] : @headings; -} - -##--------------------------------------------------------------------------- - -=head1 B<select()> - - $parser->select($section_spec1,$section_spec2,...); - -This method is used to select the particular sections and subsections of -POD documentation that are to be printed and/or processed. The existing -set of selected sections is I<replaced> with the given set of sections. -See B<add_selection()> for adding to the current set of selected -sections. - -Each of the C<$section_spec> arguments should be a section specification -as described in L<"SECTION SPECIFICATIONS">. The section specifications -are parsed by this method and the resulting regular expressions are -stored in the invoking object. - -If no C<$section_spec> arguments are given, then the existing set of -selected sections is cleared out (which means C<all> sections will be -processed). - -This method should I<not> normally be overridden by subclasses. - -=cut - -use vars qw(@selected_sections); - -sub select { - my $self = shift; - my @sections = @_; - local *myData = $self; - local $_; - -### NEED TO DISCERN A SECTION-SPEC FROM A RANGE-SPEC (look for m{^/.+/$}?) - - ##--------------------------------------------------------------------- - ## The following is a blatant hack for backward compatibility, and for - ## implementing add_selection(). If the *first* *argument* is the - ## string "+", then the remaining section specifications are *added* - ## to the current set of selections; otherwise the given section - ## specifications will *replace* the current set of selections. - ## - ## This should probably be fixed someday, but for the present time, - ## it seems incredibly unlikely that "+" would ever correspond to - ## a legitimate section heading - ##--------------------------------------------------------------------- - my $add = ($sections[0] eq "+") ? shift(@sections) : ""; - - ## Reset the set of sections to use - unless (@sections > 0) { - delete $myData{_SELECTED_SECTIONS} unless ($add); - return; - } - $myData{_SELECTED_SECTIONS} = [] - unless ($add && exists $myData{_SELECTED_SECTIONS}); - local *selected_sections = $myData{_SELECTED_SECTIONS}; - - ## Compile each spec - my $spec; - for $spec (@sections) { - if ( defined($_ = &_compile_section_spec($spec)) ) { - ## Store them in our sections array - push(@selected_sections, $_); - } - else { - carp "Ignoring section spec \"$spec\"!\n"; - } - } -} - -##--------------------------------------------------------------------------- - -=head1 B<add_selection()> - - $parser->add_selection($section_spec1,$section_spec2,...); - -This method is used to add to the currently selected sections and -subsections of POD documentation that are to be printed and/or -processed. See <select()> for replacing the currently selected sections. - -Each of the C<$section_spec> arguments should be a section specification -as described in L<"SECTION SPECIFICATIONS">. The section specifications -are parsed by this method and the resulting regular expressions are -stored in the invoking object. - -This method should I<not> normally be overridden by subclasses. - -=cut - -sub add_selection { - my $self = shift; - $self->select("+", @_); -} - -##--------------------------------------------------------------------------- - -=head1 B<clear_selections()> - - $parser->clear_selections(); - -This method takes no arguments, it has the exact same effect as invoking -<select()> with no arguments. - -=cut - -sub clear_selections { - my $self = shift; - $self->select(); -} - -##--------------------------------------------------------------------------- - -=head1 B<match_section()> - - $boolean = $parser->match_section($heading1,$heading2,...); - -Returns a value of true if the given section and subsection heading -titles match any of the currently selected section specifications in -effect from prior calls to B<select()> and B<add_selection()> (or if -there are no explictly selected/deselected sections). - -The arguments C<$heading1>, C<$heading2>, etc. are the heading titles of -the corresponding sections, subsections, etc. to try and match. If -C<$headingN> is omitted then it defaults to the current corresponding -section heading title in the input. - -This method should I<not> normally be overridden by subclasses. - -=cut - -sub match_section { - my $self = shift; - my (@headings) = @_; - local *myData = $self; - - ## Return true if no restrictions were explicitly specified - my $selections = (exists $myData{_SELECTED_SECTIONS}) - ? $myData{_SELECTED_SECTIONS} : undef; - return 1 unless ((defined $selections) && (@{$selections} > 0)); - - ## Default any unspecified sections to the current one - my @current_headings = $self->curr_headings(); - for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { - (defined $headings[$i]) or $headings[$i] = $current_headings[$i]; - } - - ## Look for a match against the specified section expressions - my ($section_spec, $regex, $negated, $match); - for $section_spec ( @{$selections} ) { - ##------------------------------------------------------ - ## Each portion of this spec must match in order for - ## the spec to be matched. So we will start with a - ## match-value of 'true' and logically 'and' it with - ## the results of matching a given element of the spec. - ##------------------------------------------------------ - $match = 1; - for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { - $regex = $section_spec->[$i]; - $negated = ($regex =~ s/^\!//); - $match &= ($negated ? ($headings[$i] !~ /${regex}/) - : ($headings[$i] =~ /${regex}/)); - last unless ($match); - } - return 1 if ($match); - } - return 0; ## no match -} - -##--------------------------------------------------------------------------- - -=head1 B<is_selected()> - - $boolean = $parser->is_selected($paragraph); - -This method is used to determine if the block of text given in -C<$paragraph> falls within the currently selected set of POD sections -and subsections to be printed or processed. This method is also -responsible for keeping track of the current input section and -subsections. It is assumed that C<$paragraph> is the most recently read -(but not yet processed) input paragraph. - -The value returned will be true if the C<$paragraph> and the rest of the -text in the same section as C<$paragraph> should be selected (included) -for processing; otherwise a false value is returned. - -=cut - -sub is_selected { - my ($self, $paragraph) = @_; - local $_; - local *myData = $self; - - $self->_init_headings() unless (defined $myData{_SECTION_HEADINGS}); - - ## Keep track of current sections levels and headings - $_ = $paragraph; - if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*)\s*$/) { - ## This is a section heading command - my ($level, $heading) = ($2, $3); - $level = 1 + (length($1) / 3) if ((! length $level) || (length $1)); - ## Reset the current section heading at this level - $myData{_SECTION_HEADINGS}->[$level - 1] = $heading; - ## Reset subsection headings of this one to empty - for (my $i = $level; $i < $MAX_HEADING_LEVEL; ++$i) { - $myData{_SECTION_HEADINGS}->[$i] = ''; - } - } - - return $self->match_section(); -} - -############################################################################# - -=head1 EXPORTED FUNCTIONS - -The following functions are exported by this module. Please note that -these are functions (not methods) and therefore C<do not> take an -implicit first argument. - -=cut - -##--------------------------------------------------------------------------- - -=head1 B<podselect()> - - podselect(\%options,@filelist); - -B<podselect> will print the raw (untranslated) POD paragraphs of all -POD sections in the given input files specified by C<@filelist> -according to the given options. - -If any argument to B<podselect> is a reference to a hash -(associative array) then the values with the following keys are -processed as follows: - -=over 4 - -=item B<-output> - -A string corresponding to the desired output file (or ">&STDOUT" -or ">&STDERR"). The default is to use standard output. - -=item B<-sections> - -A reference to an array of sections specifications (as described in -L<"SECTION SPECIFICATIONS">) which indicate the desired set of POD -sections and subsections to be selected from input. If no section -specifications are given, then all sections of the PODs are used. - -=begin _NOT_IMPLEMENTED_ - -=item B<-ranges> - -A reference to an array of range specifications (as described in -L<"RANGE SPECIFICATIONS">) which indicate the desired range of POD -paragraphs to be selected from the desired input sections. If no range -specifications are given, then all paragraphs of the desired sections -are used. - -=end _NOT_IMPLEMENTED_ - -=back - -All other arguments should correspond to the names of input files -containing POD sections. A file name of "-" or "<&STDIN" will -be interpeted to mean standard input (which is the default if no -filenames are given). - -=cut - -sub podselect { - my(@argv) = @_; - my %defaults = (); - my $pod_parser = new Pod::Select(%defaults); - my $num_inputs = 0; - my $output = ">&STDOUT"; - my %opts = (); - local $_; - for (@argv) { - if (ref($_)) { - next unless (ref($_) eq 'HASH'); - %opts = (%defaults, %{$_}); - - ##------------------------------------------------------------- - ## Need this for backward compatibility since we formerly used - ## options that were all uppercase words rather than ones that - ## looked like Unix command-line options. - ## to be uppercase keywords) - ##------------------------------------------------------------- - %opts = map { - my ($key, $val) = (lc $_, $opts{$_}); - $key =~ s/^(?=\w)/-/; - $key =~ /^-se[cl]/ and $key = '-sections'; - #! $key eq '-range' and $key .= 's'; - ($key => $val); - } (keys %opts); - - ## Process the options - (exists $opts{'-output'}) and $output = $opts{'-output'}; - - ## Select the desired sections - $pod_parser->select(@{ $opts{'-sections'} }) - if ( (defined $opts{'-sections'}) - && ((ref $opts{'-sections'}) eq 'ARRAY') ); - - #! ## Select the desired paragraph ranges - #! $pod_parser->select(@{ $opts{'-ranges'} }) - #! if ( (defined $opts{'-ranges'}) - #! && ((ref $opts{'-ranges'}) eq 'ARRAY') ); - } - else { - $pod_parser->parse_from_file($_, $output); - ++$num_inputs; - } - } - $pod_parser->parse_from_file("-") unless ($num_inputs > 0); -} - -############################################################################# - -=head1 PRIVATE METHODS AND DATA - -B<Pod::Select> makes uses a number of internal methods and data fields -which clients should not need to see or use. For the sake of avoiding -name collisions with 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::Select> 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::Select> begin with a -prefix of "_" and match the regular expression C</^_\w+$/>. - -=cut - -##--------------------------------------------------------------------------- - -=begin _PRIVATE_ - -=head1 B<_compile_section_spec()> - - $listref = $parser->_compile_section_spec($section_spec); - -This function (note it is a function and I<not> a method) takes a -section specification (as described in L<"SECTION SPECIFICATIONS">) -given in C<$section_sepc>, and compiles it into a list of regular -expressions. If C<$section_spec> has no syntax errors, then a reference -to the list (array) of corresponding regular expressions is returned; -otherwise C<undef> is returned and an error message is printed (using -B<carp>) for each invalid regex. - -=end _PRIVATE_ - -=cut - -sub _compile_section_spec { - my ($section_spec) = @_; - my (@regexs, $negated); - - ## Compile the spec into a list of regexs - local $_ = $section_spec; - s|\\\\|\001|g; ## handle escaped backward slashes - s|\\/|\002|g; ## handle escaped forward slashes - - ## Parse the regexs for the heading titles - @regexs = split('/', $_, $MAX_HEADING_LEVEL); - - ## Set default regex for ommitted levels - for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { - $regexs[$i] = '.*' unless ((defined $regexs[$i]) - && (length $regexs[$i])); - } - ## Modify the regexs as needed and validate their syntax - my $bad_regexs = 0; - for (@regexs) { - $_ .= '.+' if ($_ eq '!'); - s|\001|\\\\|g; ## restore escaped backward slashes - s|\002|\\/|g; ## restore escaped forward slashes - $negated = s/^\!//; ## check for negation - eval "/$_/"; ## check regex syntax - if ($@) { - ++$bad_regexs; - carp "Bad regular expression /$_/ in \"$section_spec\": $@\n"; - } - else { - ## Add the forward and rear anchors (and put the negator back) - $_ = '^' . $_ unless (/^\^/); - $_ = $_ . '$' unless (/\$$/); - $_ = '!' . $_ if ($negated); - } - } - return (! $bad_regexs) ? [ @regexs ] : undef; -} - -##--------------------------------------------------------------------------- - -=begin _PRIVATE_ - -=head2 $self->{_SECTION_HEADINGS} - -A reference to an array of the current section heading titles for each -heading level (note that the first heading level title is at index 0). - -=end _PRIVATE_ - -=cut - -##--------------------------------------------------------------------------- - -=begin _PRIVATE_ - -=head2 $self->{_SELECTED_SECTIONS} - -A reference to an array of references to arrays. Each subarray is a list -of anchored regular expressions (preceded by a "!" if the expression is to -be negated). The index of the expression in the subarray should correspond -to the index of the heading title in C<$self-E<gt>{_SECTION_HEADINGS}> -that it is to be matched against. - -=end _PRIVATE_ - -=cut - -############################################################################# - -=head1 SEE ALSO - -L<Pod::Parser> - -=head1 AUTHOR - -Brad Appleton E<lt>bradapp@enteract.comE<gt> - -Based on code for B<pod2text> written by -Tom Christiansen E<lt>tchrist@mox.perl.comE<gt> - -=cut - -1; - diff --git a/contrib/perl5/lib/Pod/Text.pm b/contrib/perl5/lib/Pod/Text.pm deleted file mode 100644 index 9936025..0000000 --- a/contrib/perl5/lib/Pod/Text.pm +++ /dev/null @@ -1,827 +0,0 @@ -# Pod::Text -- Convert POD data to formatted ASCII text. -# $Id: Text.pm,v 2.8 2001/02/10 06:50:23 eagle Exp $ -# -# Copyright 1999, 2000, 2001 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::Text; - -require 5.004; - -use Carp qw(carp croak); -use Exporter (); -use Pod::Select (); - -use strict; -use vars qw(@ISA @EXPORT %ESCAPES $VERSION); - -# We inherit from Pod::Select instead of Pod::Parser so that we can be used -# by Pod::Usage. -@ISA = qw(Pod::Select Exporter); - -# We have to export pod2text for backward compatibility. -@EXPORT = qw(pod2text); - -# Don't use the CVS revision as the version, since this module is also in -# Perl core and too many things could munge CVS magic revision strings. -# This number should ideally be the same as the CVS revision in podlators, -# however. -$VERSION = 2.08; - - -############################################################################ -# 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. :) -# "iexcl" to "divide" added by Tim Jenness. -%ESCAPES = ( - 'amp' => '&', # ampersand - 'lt' => '<', # left chevron, less-than - 'gt' => '>', # right chevron, greater-than - 'quot' => '"', # double quote - 'sol' => '/', # solidus (forward slash) - 'verbar' => '|', # vertical bar - - "Aacute" => "\xC1", # capital A, acute accent - "aacute" => "\xE1", # small a, acute accent - "Acirc" => "\xC2", # capital A, circumflex accent - "acirc" => "\xE2", # small a, circumflex accent - "AElig" => "\xC6", # capital AE diphthong (ligature) - "aelig" => "\xE6", # small ae diphthong (ligature) - "Agrave" => "\xC0", # capital A, grave accent - "agrave" => "\xE0", # small a, grave accent - "Aring" => "\xC5", # capital A, ring - "aring" => "\xE5", # small a, ring - "Atilde" => "\xC3", # capital A, tilde - "atilde" => "\xE3", # small a, tilde - "Auml" => "\xC4", # capital A, dieresis or umlaut mark - "auml" => "\xE4", # small a, dieresis or umlaut mark - "Ccedil" => "\xC7", # capital C, cedilla - "ccedil" => "\xE7", # small c, cedilla - "Eacute" => "\xC9", # capital E, acute accent - "eacute" => "\xE9", # small e, acute accent - "Ecirc" => "\xCA", # capital E, circumflex accent - "ecirc" => "\xEA", # small e, circumflex accent - "Egrave" => "\xC8", # capital E, grave accent - "egrave" => "\xE8", # small e, grave accent - "ETH" => "\xD0", # capital Eth, Icelandic - "eth" => "\xF0", # small eth, Icelandic - "Euml" => "\xCB", # capital E, dieresis or umlaut mark - "euml" => "\xEB", # small e, dieresis or umlaut mark - "Iacute" => "\xCC", # capital I, acute accent - "iacute" => "\xEC", # small i, acute accent - "Icirc" => "\xCE", # capital I, circumflex accent - "icirc" => "\xEE", # small i, circumflex accent - "Igrave" => "\xCD", # capital I, grave accent - "igrave" => "\xED", # small i, grave accent - "Iuml" => "\xCF", # capital I, dieresis or umlaut mark - "iuml" => "\xEF", # small i, dieresis or umlaut mark - "Ntilde" => "\xD1", # capital N, tilde - "ntilde" => "\xF1", # small n, tilde - "Oacute" => "\xD3", # capital O, acute accent - "oacute" => "\xF3", # small o, acute accent - "Ocirc" => "\xD4", # capital O, circumflex accent - "ocirc" => "\xF4", # small o, circumflex accent - "Ograve" => "\xD2", # capital O, grave accent - "ograve" => "\xF2", # small o, grave accent - "Oslash" => "\xD8", # capital O, slash - "oslash" => "\xF8", # small o, slash - "Otilde" => "\xD5", # capital O, tilde - "otilde" => "\xF5", # small o, tilde - "Ouml" => "\xD6", # capital O, dieresis or umlaut mark - "ouml" => "\xF6", # small o, dieresis or umlaut mark - "szlig" => "\xDF", # small sharp s, German (sz ligature) - "THORN" => "\xDE", # capital THORN, Icelandic - "thorn" => "\xFE", # small thorn, Icelandic - "Uacute" => "\xDA", # capital U, acute accent - "uacute" => "\xFA", # small u, acute accent - "Ucirc" => "\xDB", # capital U, circumflex accent - "ucirc" => "\xFB", # small u, circumflex accent - "Ugrave" => "\xD9", # capital U, grave accent - "ugrave" => "\xF9", # small u, grave accent - "Uuml" => "\xDC", # capital U, dieresis or umlaut mark - "uuml" => "\xFC", # small u, dieresis or umlaut mark - "Yacute" => "\xDD", # capital Y, acute accent - "yacute" => "\xFD", # small y, acute accent - "yuml" => "\xFF", # small y, dieresis or umlaut mark - - "laquo" => "\xAB", # left pointing double angle quotation mark - "lchevron" => "\xAB", # synonym (backwards compatibility) - "raquo" => "\xBB", # right pointing double angle quotation mark - "rchevron" => "\xBB", # synonym (backwards compatibility) - - "iexcl" => "\xA1", # inverted exclamation mark - "cent" => "\xA2", # cent sign - "pound" => "\xA3", # (UK) pound sign - "curren" => "\xA4", # currency sign - "yen" => "\xA5", # yen sign - "brvbar" => "\xA6", # broken vertical bar - "sect" => "\xA7", # section sign - "uml" => "\xA8", # diaresis - "copy" => "\xA9", # Copyright symbol - "ordf" => "\xAA", # feminine ordinal indicator - "not" => "\xAC", # not sign - "shy" => "\xAD", # soft hyphen - "reg" => "\xAE", # registered trademark - "macr" => "\xAF", # macron, overline - "deg" => "\xB0", # degree sign - "plusmn" => "\xB1", # plus-minus sign - "sup2" => "\xB2", # superscript 2 - "sup3" => "\xB3", # superscript 3 - "acute" => "\xB4", # acute accent - "micro" => "\xB5", # micro sign - "para" => "\xB6", # pilcrow sign = paragraph sign - "middot" => "\xB7", # middle dot = Georgian comma - "cedil" => "\xB8", # cedilla - "sup1" => "\xB9", # superscript 1 - "ordm" => "\xBA", # masculine ordinal indicator - "frac14" => "\xBC", # vulgar fraction one quarter - "frac12" => "\xBD", # vulgar fraction one half - "frac34" => "\xBE", # vulgar fraction three quarters - "iquest" => "\xBF", # inverted question mark - "times" => "\xD7", # multiplication sign - "divide" => "\xF7", # division sign -); - - -############################################################################ -# Initialization -############################################################################ - -# Initialize the object. Must be sure to call our parent initializer. -sub initialize { - my $self = shift; - - $$self{alt} = 0 unless defined $$self{alt}; - $$self{indent} = 4 unless defined $$self{indent}; - $$self{loose} = 0 unless defined $$self{loose}; - $$self{sentence} = 0 unless defined $$self{sentence}; - $$self{width} = 76 unless defined $$self{width}; - - # Figure out what quotes we'll be using for C<> text. - $$self{quotes} ||= '"'; - if ($$self{quotes} eq 'none') { - $$self{LQUOTE} = $$self{RQUOTE} = ''; - } elsif (length ($$self{quotes}) == 1) { - $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes}; - } elsif ($$self{quotes} =~ /^(.)(.)$/ - || $$self{quotes} =~ /^(..)(..)$/) { - $$self{LQUOTE} = $1; - $$self{RQUOTE} = $2; - } else { - croak qq(Invalid quote specification "$$self{quotes}"); - } - - $$self{INDENTS} = []; # Stack of indentations. - $$self{MARGIN} = $$self{indent}; # Current left margin in spaces. - - $self->SUPER::initialize; -} - - -############################################################################ -# Core overrides -############################################################################ - -# Called for each command paragraph. Gets the command, the associated -# paragraph, the line number, and a Pod::Paragraph object. Just dispatches -# the command to a method named the same as the command. =cut is handled -# internally by Pod::Parser. -sub command { - my $self = shift; - my $command = shift; - return if $command eq 'pod'; - return if ($$self{EXCLUDE} && $command ne 'end'); - $self->item ("\n") if defined $$self{ITEM}; - if ($self->can ('cmd_' . $command)) { - $command = 'cmd_' . $command; - $self->$command (@_); - } else { - my ($text, $line, $paragraph) = @_; - my $file; - ($file, $line) = $paragraph->file_line; - $text =~ s/\n+\z//; - $text = " $text" if ($text =~ /^\S/); - warn qq($file:$line: Unknown command paragraph "=$command$text"\n); - return; - } -} - -# Called for a verbatim paragraph. Gets the paragraph, the line number, and -# a Pod::Paragraph object. Just output it verbatim, but with tabs converted -# to spaces. -sub verbatim { - my $self = shift; - return if $$self{EXCLUDE}; - $self->item if defined $$self{ITEM}; - local $_ = shift; - return if /^\s*$/; - s/^(\s*\S+)/(' ' x $$self{MARGIN}) . $1/gme; - $self->output ($_); -} - -# Called for a regular text block. Gets the paragraph, the line number, and -# a Pod::Paragraph object. Perform interpolation and output the results. -sub textblock { - my $self = shift; - return if $$self{EXCLUDE}; - $self->output ($_[0]), return if $$self{VERBATIM}; - local $_ = shift; - my $line = shift; - - # Perform a little magic to collapse multiple L<> references. This is - # here mostly for backwards-compatibility. We'll just rewrite the whole - # thing into actual text at this part, bypassing the whole internal - # sequence parsing thing. - s{ - ( - L< # A link of the form L</something>. - / - ( - [:\w]+ # The item has to be a simple word... - (\(\))? # ...or simple function. - ) - > - ( - ,?\s+(and\s+)? # Allow lots of them, conjuncted. - L< - / - ( - [:\w]+ - (\(\))? - ) - > - )+ - ) - } { - local $_ = $1; - s%L</([^>]+)>%$1%g; - my @items = split /(?:,?\s+(?:and\s+)?)/; - my $string = "the "; - my $i; - for ($i = 0; $i < @items; $i++) { - $string .= $items[$i]; - $string .= ", " if @items > 2 && $i != $#items; - $string .= " and " if ($i == $#items - 1); - } - $string .= " entries elsewhere in this document"; - $string; - }gex; - - # Now actually interpolate and output the paragraph. - $_ = $self->interpolate ($_, $line); - s/\s+$/\n/; - if (defined $$self{ITEM}) { - $self->item ($_ . "\n"); - } else { - $self->output ($self->reformat ($_ . "\n")); - } -} - -# Called for an interior sequence. Gets the command, argument, and a -# Pod::InteriorSequence object and is expected to return the resulting text. -# Calls code, bold, italic, file, and link to handle those types of -# sequences, and handles S<>, E<>, X<>, and Z<> directly. -sub interior_sequence { - my $self = shift; - my $command = shift; - local $_ = shift; - return '' if ($command eq 'X' || $command eq 'Z'); - - # Expand escapes into the actual character now, carping if invalid. - if ($command eq 'E') { - if (/^\d+$/) { - return chr; - } else { - return $ESCAPES{$_} if defined $ESCAPES{$_}; - carp "Unknown escape: E<$_>"; - return "E<$_>"; - } - } - - # For all the other sequences, empty content produces no output. - return if $_ eq ''; - - # For S<>, compress all internal whitespace and then map spaces to \01. - # When we output the text, we'll map this back. - if ($command eq 'S') { - s/\s{2,}/ /g; - tr/ /\01/; - return $_; - } - - # Anything else needs to get dispatched to another method. - if ($command eq 'B') { return $self->seq_b ($_) } - elsif ($command eq 'C') { return $self->seq_c ($_) } - elsif ($command eq 'F') { return $self->seq_f ($_) } - elsif ($command eq 'I') { return $self->seq_i ($_) } - elsif ($command eq 'L') { return $self->seq_l ($_) } - else { carp "Unknown sequence $command<$_>" } -} - -# Called for each paragraph that's actually part of the POD. We take -# advantage of this opportunity to untabify the input. -sub preprocess_paragraph { - my $self = shift; - local $_ = shift; - 1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me; - $_; -} - - -############################################################################ -# Command paragraphs -############################################################################ - -# All command paragraphs take the paragraph and the line number. - -# First level heading. -sub cmd_head1 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $_ = $self->interpolate ($_, shift); - if ($$self{alt}) { - $self->output ("\n==== $_ ====\n\n"); - } else { - $_ .= "\n" if $$self{loose}; - $self->output ($_ . "\n"); - } -} - -# Second level heading. -sub cmd_head2 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $_ = $self->interpolate ($_, shift); - if ($$self{alt}) { - $self->output ("\n== $_ ==\n\n"); - } else { - $self->output (' ' x ($$self{indent} / 2) . $_ . "\n\n"); - } -} - -# Third level heading. -sub cmd_head3 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $_ = $self->interpolate ($_, shift); - if ($$self{alt}) { - $self->output ("\n= $_ =\n\n"); - } else { - $self->output (' ' x ($$self{indent} * 2 / 3 + 0.5) . $_ . "\n\n"); - } -} - -# Third level heading. -sub cmd_head4 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $_ = $self->interpolate ($_, shift); - if ($$self{alt}) { - $self->output ("\n- $_ -\n\n"); - } else { - $self->output (' ' x ($$self{indent} * 3 / 4 + 0.5) . $_ . "\n\n"); - } -} - -# Start a list. -sub cmd_over { - my $self = shift; - local $_ = shift; - unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} } - push (@{ $$self{INDENTS} }, $$self{MARGIN}); - $$self{MARGIN} += ($_ + 0); -} - -# End a list. -sub cmd_back { - my $self = shift; - $$self{MARGIN} = pop @{ $$self{INDENTS} }; - unless (defined $$self{MARGIN}) { - carp "Unmatched =back"; - $$self{MARGIN} = $$self{indent}; - } -} - -# An individual list item. -sub cmd_item { - my $self = shift; - if (defined $$self{ITEM}) { $self->item } - local $_ = shift; - s/\s+$//; - $$self{ITEM} = $self->interpolate ($_); -} - -# Begin a block for a particular translator. Setting VERBATIM triggers -# special handling in textblock(). -sub cmd_begin { - my $self = shift; - local $_ = shift; - my ($kind) = /^(\S+)/ or return; - if ($kind eq 'text') { - $$self{VERBATIM} = 1; - } else { - $$self{EXCLUDE} = 1; - } -} - -# End a block for a particular translator. We assume that all =begin/=end -# pairs are properly closed. -sub cmd_end { - my $self = shift; - $$self{EXCLUDE} = 0; - $$self{VERBATIM} = 0; -} - -# One paragraph for a particular translator. Ignore it unless it's intended -# for text, in which case we treat it as a verbatim text block. -sub cmd_for { - my $self = shift; - local $_ = shift; - my $line = shift; - return unless s/^text\b[ \t]*\n?//; - $self->verbatim ($_, $line); -} - - -############################################################################ -# Interior sequences -############################################################################ - -# The simple formatting ones. These are here mostly so that subclasses can -# override them and do more complicated things. -sub seq_b { return $_[0]{alt} ? "``$_[1]''" : $_[1] } -sub seq_f { return $_[0]{alt} ? "\"$_[1]\"" : $_[1] } -sub seq_i { return '*' . $_[1] . '*' } -sub seq_c { - return $_[0]{alt} ? "``$_[1]''" : "$_[0]{LQUOTE}$_[1]$_[0]{RQUOTE}" -} - -# The complicated one. Handle links. Since this is plain text, we can't -# actually make any real links, so this is all to figure out what text we -# print out. -sub seq_l { - my $self = shift; - local $_ = shift; - - # Smash whitespace in case we were split across multiple lines. - s/\s+/ /g; - - # If we were given any explicit text, just output it. - if (/^([^|]+)\|/) { return $1 } - - # Okay, leading and trailing whitespace isn't important; get rid of it. - s/^\s+//; - s/\s+$//; - - # If the argument looks like a URL, return it verbatim. This only - # handles URLs that use the server syntax. - if (m%^[a-z]+://\S+$%) { return $_ } - - # Default to using the whole content of the link entry as a section - # name. Note that L<manpage/> forces a manpage interpretation, as does - # something looking like L<manpage(section)>. The latter is an - # enhancement over the original Pod::Text. - my ($manpage, $section) = ('', $_); - if (/^"\s*(.*?)\s*"$/) { - $section = '"' . $1 . '"'; - } elsif (m/^[-:.\w]+(?:\(\S+\))?$/) { - ($manpage, $section) = ($_, ''); - } elsif (m%/%) { - ($manpage, $section) = split (/\s*\/\s*/, $_, 2); - } - - # Now build the actual output text. - my $text = ''; - if (!length $section) { - $text = "the $manpage manpage" if length $manpage; - } elsif ($section =~ /^[:\w]+(?:\(\))?/) { - $text .= 'the ' . $section . ' entry'; - $text .= (length $manpage) ? " in the $manpage manpage" - : " elsewhere in this document"; - } else { - $section =~ s/^\"\s*//; - $section =~ s/\s*\"$//; - $text .= 'the section on "' . $section . '"'; - $text .= " in the $manpage manpage" if length $manpage; - } - $text; -} - - -############################################################################ -# List handling -############################################################################ - -# This method is called whenever an =item command is complete (in other -# words, we've seen its associated paragraph or know for certain that it -# doesn't have one). It gets the paragraph associated with the item as an -# argument. If that argument is empty, just output the item tag; if it -# contains a newline, output the item tag followed by the newline. -# Otherwise, see if there's enough room for us to output the item tag in the -# margin of the text or if we have to put it on a separate line. -sub item { - my $self = shift; - local $_ = shift; - my $tag = $$self{ITEM}; - unless (defined $tag) { - carp "item called without tag"; - return; - } - undef $$self{ITEM}; - my $indent = $$self{INDENTS}[-1]; - unless (defined $indent) { $indent = $$self{indent} } - my $space = ' ' x $indent; - $space =~ s/^ /:/ if $$self{alt}; - if (!$_ || /^\s+$/ || ($$self{MARGIN} - $indent < length ($tag) + 1)) { - my $margin = $$self{MARGIN}; - $$self{MARGIN} = $indent; - my $output = $self->reformat ($tag); - $output =~ s/\n*$/\n/; - $self->output ($output); - $$self{MARGIN} = $margin; - $self->output ($self->reformat ($_)) if /\S/; - } else { - $_ = $self->reformat ($_); - s/^ /:/ if ($$self{alt} && $indent > 0); - my $tagspace = ' ' x length $tag; - s/^($space)$tagspace/$1$tag/ or warn "Bizarre space in item"; - $self->output ($_); - } -} - - -############################################################################ -# Output formatting -############################################################################ - -# Wrap a line, indenting by the current left margin. We can't use -# Text::Wrap because it plays games with tabs. We can't use formline, even -# though we'd really like to, because it screws up non-printing characters. -# So we have to do the wrapping ourselves. -sub wrap { - my $self = shift; - local $_ = shift; - my $output = ''; - my $spaces = ' ' x $$self{MARGIN}; - my $width = $$self{width} - $$self{MARGIN}; - while (length > $width) { - if (s/^([^\n]{0,$width})\s+// || s/^([^\n]{$width})//) { - $output .= $spaces . $1 . "\n"; - } else { - last; - } - } - $output .= $spaces . $_; - $output =~ s/\s+$/\n\n/; - $output; -} - -# Reformat a paragraph of text for the current margin. Takes the text to -# reformat and returns the formatted text. -sub reformat { - my $self = shift; - local $_ = shift; - - # If we're trying to preserve two spaces after sentences, do some - # munging to support that. Otherwise, smash all repeated whitespace. - if ($$self{sentence}) { - s/ +$//mg; - s/\.\n/. \n/g; - s/\n/ /g; - s/ +/ /g; - } else { - s/\s+/ /g; - } - $self->wrap ($_); -} - -# Output text to the output device. -sub output { $_[1] =~ tr/\01/ /; print { $_[0]->output_handle } $_[1] } - - -############################################################################ -# Backwards compatibility -############################################################################ - -# The old Pod::Text module did everything in a pod2text() function. This -# tries to provide the same interface for legacy applications. -sub pod2text { - my @args; - - # This is really ugly; I hate doing option parsing in the middle of a - # module. But the old Pod::Text module supported passing flags to its - # entry function, so handle -a and -<number>. - while ($_[0] =~ /^-/) { - my $flag = shift; - if ($flag eq '-a') { push (@args, alt => 1) } - elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) } - else { - unshift (@_, $flag); - last; - } - } - - # Now that we know what arguments we're using, create the parser. - my $parser = Pod::Text->new (@args); - - # If two arguments were given, the second argument is going to be a file - # handle. That means we want to call parse_from_filehandle(), which - # means we need to turn the first argument into a file handle. Magic - # open will handle the <&STDIN case automagically. - if (defined $_[1]) { - my @fhs = @_; - local *IN; - unless (open (IN, $fhs[0])) { - croak ("Can't open $fhs[0] for reading: $!\n"); - return; - } - $fhs[0] = \*IN; - return $parser->parse_from_filehandle (@fhs); - } else { - return $parser->parse_from_file (@_); - } -} - - -############################################################################ -# Module return value and documentation -############################################################################ - -1; -__END__ - -=head1 NAME - -Pod::Text - Convert POD data to formatted ASCII text - -=head1 SYNOPSIS - - use Pod::Text; - my $parser = Pod::Text->new (sentence => 0, width => 78); - - # Read POD from STDIN and write to STDOUT. - $parser->parse_from_filehandle; - - # Read POD from file.pod and write to file.txt. - $parser->parse_from_file ('file.pod', 'file.txt'); - -=head1 DESCRIPTION - -Pod::Text is a module that can convert documentation in the POD format (the -preferred language for documenting Perl) into formatted ASCII. It uses no -special formatting controls or codes whatsoever, and its output is therefore -suitable for nearly any device. - -As a derived class from Pod::Parser, Pod::Text supports the same methods and -interfaces. See L<Pod::Parser> for all the details; briefly, one creates a -new parser with C<Pod::Text-E<gt>new()> and then calls either -parse_from_filehandle() or parse_from_file(). - -new() can take options, in the form of key/value pairs, that control the -behavior of the parser. The currently recognized options are: - -=over 4 - -=item alt - -If set to a true value, selects an alternate output format that, among other -things, uses a different heading style and marks C<=item> entries with a -colon in the left margin. Defaults to false. - -=item indent - -The number of spaces to indent regular text, and the default indentation for -C<=over> blocks. Defaults to 4. - -=item loose - -If set to a true value, a blank line is printed after a C<=head1> heading. -If set to false (the default), no blank line is printed after C<=head1>, -although one is still printed after C<=head2>. This is the default because -it's the expected formatting for manual pages; if you're formatting -arbitrary text documents, setting this to true may result in more pleasing -output. - -=item quotes - -Sets the quote marks used to surround CE<lt>> text. If the value is a -single character, it is used as both the left and right quote; if it is two -characters, the first character is used as the left quote and the second as -the right quoted; and if it is four characters, the first two are used as -the left quote and the second two as the right quote. - -This may also be set to the special value C<none>, in which case no quote -marks are added around CE<lt>> text. - -=item sentence - -If set to a true value, Pod::Text will assume that each sentence ends in two -spaces, and will try to preserve that spacing. If set to false, all -consecutive whitespace in non-verbatim paragraphs is compressed into a -single space. Defaults to true. - -=item width - -The column at which to wrap text on the right-hand side. Defaults to 76. - -=back - -The standard Pod::Parser method parse_from_filehandle() takes up to two -arguments, the first being the file handle to read POD from and the second -being the file handle to write the formatted output to. The first defaults -to STDIN if not given, and the second defaults to STDOUT. The method -parse_from_file() is almost identical, except that its two arguments are the -input and output disk files instead. See L<Pod::Parser> for the specific -details. - -=head1 DIAGNOSTICS - -=over 4 - -=item Bizarre space in item - -(W) Something has gone wrong in internal C<=item> processing. This message -indicates a bug in Pod::Text; you should never see it. - -=item Can't open %s for reading: %s - -(F) Pod::Text was invoked via the compatibility mode pod2text() interface -and the input file it was given could not be opened. - -=item Invalid quote specification "%s" - -(F) The quote specification given (the quotes option to the constructor) was -invalid. A quote specification must be one, two, or four characters long. - -=item %s:%d: Unknown command paragraph "%s". - -(W) The POD source contained a non-standard command paragraph (something of -the form C<=command args>) that Pod::Man didn't know about. It was ignored. - -=item Unknown escape: %s - -(W) The POD source contained an C<EE<lt>E<gt>> escape that Pod::Text didn't -know about. - -=item Unknown sequence: %s - -(W) The POD source contained a non-standard internal sequence (something of -the form C<XE<lt>E<gt>>) that Pod::Text didn't know about. - -=item Unmatched =back - -(W) Pod::Text encountered a C<=back> command that didn't correspond to an -C<=over> command. - -=back - -=head1 RESTRICTIONS - -Embedded Ctrl-As (octal 001) in the input will be mapped to spaces on -output, due to an internal implementation detail. - -=head1 NOTES - -This is a replacement for an earlier Pod::Text module written by Tom -Christiansen. It has a revamped interface, since it now uses Pod::Parser, -but an interface roughly compatible with the old Pod::Text::pod2text() -function is still available. Please change to the new calling convention, -though. - -The original Pod::Text contained code to do formatting via termcap -sequences, although it wasn't turned on by default and it was problematic to -get it to work at all. This rewrite doesn't even try to do that, but a -subclass of it does. Look for L<Pod::Text::Termcap|Pod::Text::Termcap>. - -=head1 SEE ALSO - -L<Pod::Parser|Pod::Parser>, L<Pod::Text::Termcap|Pod::Text::Termcap>, -pod2text(1) - -=head1 AUTHOR - -Russ Allbery E<lt>rra@stanford.eduE<gt>, based I<very> heavily on the -original Pod::Text by Tom Christiansen E<lt>tchrist@mox.perl.comE<gt> and -its conversion to Pod::Parser by Brad Appleton -E<lt>bradapp@enteract.comE<gt>. - -=cut diff --git a/contrib/perl5/lib/Pod/Text/Color.pm b/contrib/perl5/lib/Pod/Text/Color.pm deleted file mode 100644 index e943216..0000000 --- a/contrib/perl5/lib/Pod/Text/Color.pm +++ /dev/null @@ -1,128 +0,0 @@ -# Pod::Text::Color -- Convert POD data to formatted color ASCII text -# $Id: Color.pm,v 0.6 2000/12/25 12:52:39 eagle Exp $ -# -# Copyright 1999 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 is just a basic proof of concept. It should later be modified to -# make better use of color, take options changing what colors are used for -# what text, and the like. - -############################################################################ -# Modules and declarations -############################################################################ - -package Pod::Text::Color; - -require 5.004; - -use Pod::Text (); -use Term::ANSIColor qw(colored); - -use strict; -use vars qw(@ISA $VERSION); - -@ISA = qw(Pod::Text); - -# Don't use the CVS revision as the version, since this module is also in -# Perl core and too many things could munge CVS magic revision strings. -# This number should ideally be the same as the CVS revision in podlators, -# however. -$VERSION = 0.06; - - -############################################################################ -# Overrides -############################################################################ - -# Make level one headings bold. -sub cmd_head1 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $self->SUPER::cmd_head1 (colored ($_, 'bold')); -} - -# Make level two headings bold. -sub cmd_head2 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $self->SUPER::cmd_head2 (colored ($_, 'bold')); -} - -# Fix the various interior sequences. -sub seq_b { return colored ($_[1], 'bold') } -sub seq_f { return colored ($_[1], 'cyan') } -sub seq_i { return colored ($_[1], 'yellow') } - -# We unfortunately have to override the wrapping code here, since the normal -# wrapping code gets really confused by all the escape sequences. -sub wrap { - my $self = shift; - local $_ = shift; - my $output = ''; - my $spaces = ' ' x $$self{MARGIN}; - my $width = $$self{width} - $$self{MARGIN}; - while (length > $width) { - if (s/^((?:(?:\e\[[\d;]+m)?[^\n]){0,$width})\s+// - || s/^((?:(?:\e\[[\d;]+m)?[^\n]){$width})//) { - $output .= $spaces . $1 . "\n"; - } else { - last; - } - } - $output .= $spaces . $_; - $output =~ s/\s+$/\n\n/; - $output; -} - -############################################################################ -# Module return value and documentation -############################################################################ - -1; -__END__ - -=head1 NAME - -Pod::Text::Color - Convert POD data to formatted color ASCII text - -=head1 SYNOPSIS - - use Pod::Text::Color; - my $parser = Pod::Text::Color->new (sentence => 0, width => 78); - - # Read POD from STDIN and write to STDOUT. - $parser->parse_from_filehandle; - - # Read POD from file.pod and write to file.txt. - $parser->parse_from_file ('file.pod', 'file.txt'); - -=head1 DESCRIPTION - -Pod::Text::Color is a simple subclass of Pod::Text that highlights output -text using ANSI color escape sequences. Apart from the color, it in all -ways functions like Pod::Text. See L<Pod::Text> for details and available -options. - -Term::ANSIColor is used to get colors and therefore must be installed to use -this module. - -=head1 BUGS - -This is just a basic proof of concept. It should be seriously expanded to -support configurable coloration via options passed to the constructor, and -B<pod2text> should be taught about those. - -=head1 SEE ALSO - -L<Pod::Text|Pod::Text>, L<Pod::Parser|Pod::Parser> - -=head1 AUTHOR - -Russ Allbery E<lt>rra@stanford.eduE<gt>. - -=cut diff --git a/contrib/perl5/lib/Pod/Text/Overstrike.pm b/contrib/perl5/lib/Pod/Text/Overstrike.pm deleted file mode 100644 index c9f0789..0000000 --- a/contrib/perl5/lib/Pod/Text/Overstrike.pm +++ /dev/null @@ -1,160 +0,0 @@ -# Pod::Text::Overstrike -- Convert POD data to formatted overstrike text -# $Id: Overstrike.pm,v 1.1 2000/12/25 12:51:23 eagle Exp $ -# -# Created by Joe Smith <Joe.Smith@inwap.com> 30-Nov-2000 -# (based on Pod::Text::Color 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 was written because the output from: -# -# pod2text Text.pm > plain.txt; less plain.txt -# -# is not as rich as the output from -# -# pod2man Text.pm | nroff -man > fancy.txt; less fancy.txt -# -# and because both Pod::Text::Color and Pod::Text::Termcap are not device -# independent. - -############################################################################ -# Modules and declarations -############################################################################ - -package Pod::Text::Overstrike; - -require 5.004; - -use Pod::Text (); - -use strict; -use vars qw(@ISA $VERSION); - -@ISA = qw(Pod::Text); - -# Don't use the CVS revision as the version, since this module is also in -# Perl core and too many things could munge CVS magic revision strings. -# This number should ideally be the same as the CVS revision in podlators, -# however. -$VERSION = 1.01; - - -############################################################################ -# Overrides -############################################################################ - -# Make level one headings bold, overridding any existing formatting. -sub cmd_head1 { - my $self = shift; - local $_ = shift; - s/\s+$//; - s/(.)\cH\1//g; - s/_\cH//g; - s/(.)/$1\b$1/g; - $self->SUPER::cmd_head1 ($_); -} - -# Make level two headings bold, overriding any existing formatting. -sub cmd_head2 { - my $self = shift; - local $_ = shift; - s/\s+$//; - s/(.)\cH\1//g; - s/_\cH//g; - s/(.)/$1\b$1/g; - $self->SUPER::cmd_head2 ($_); -} - -# Make level three headings underscored, overriding any existing formatting. -sub cmd_head3 { - my $self = shift; - local $_ = shift; - s/\s+$//; - s/(.)\cH\1//g; - s/_\cH//g; - s/(.)/_\b$1/g; - $self->SUPER::cmd_head3 ($_); -} - -# Fix the various interior sequences. -sub seq_b { local $_ = $_[1]; s/(.)\cH\1//g; s/_\cH//g; s/(.)/$1\b$1/g; $_ } -sub seq_f { local $_ = $_[1]; s/(.)\cH\1//g; s/_\cH//g; s/(.)/_\b$1/g; $_ } -sub seq_i { local $_ = $_[1]; s/(.)\cH\1//g; s/_\cH//g; s/(.)/_\b$1/g; $_ } - -# We unfortunately have to override the wrapping code here, since the normal -# wrapping code gets really confused by all the escape sequences. -sub wrap { - my $self = shift; - local $_ = shift; - my $output = ''; - my $spaces = ' ' x $$self{MARGIN}; - my $width = $$self{width} - $$self{MARGIN}; - while (length > $width) { - if (s/^((?:(?:[^\n]\cH)?[^\n]){0,$width})\s+// - || s/^((?:(?:[^\n]\cH)?[^\n]){$width})//) { - $output .= $spaces . $1 . "\n"; - } else { - last; - } - } - $output .= $spaces . $_; - $output =~ s/\s+$/\n\n/; - $output; -} - -############################################################################ -# Module return value and documentation -############################################################################ - -1; -__END__ - -=head1 NAME - -Pod::Text::Overstrike - Convert POD data to formatted overstrike text - -=head1 SYNOPSIS - - use Pod::Text::Overstrike; - my $parser = Pod::Text::Overstrike->new (sentence => 0, width => 78); - - # Read POD from STDIN and write to STDOUT. - $parser->parse_from_filehandle; - - # Read POD from file.pod and write to file.txt. - $parser->parse_from_file ('file.pod', 'file.txt'); - -=head1 DESCRIPTION - -Pod::Text::Overstrike is a simple subclass of Pod::Text that highlights -output text using overstrike sequences, in a manner similar to nroff. -Characters in bold text are overstruck (character, backspace, character) and -characters in underlined text are converted to overstruck underscores -(underscore, backspace, character). This format was originally designed for -hardcopy terminals and/or lineprinters, yet is readable on softcopy (CRT) -terminals. - -Overstruck text is best viewed by page-at-a-time programs that take -advantage of the terminal's B<stand-out> and I<underline> capabilities, such -as the less program on Unix. - -Apart from the overstrike, it in all ways functions like Pod::Text. See -L<Pod::Text> for details and available options. - -=head1 BUGS - -Currently, the outermost formatting instruction wins, so for example -underlined text inside a region of bold text is displayed as simply bold. -There may be some better approach possible. - -=head1 SEE ALSO - -L<Pod::Text|Pod::Text>, L<Pod::Parser|Pod::Parser> - -=head1 AUTHOR - -Joe Smith E<lt>Joe.Smith@inwap.comE<gt>, using the framework created by Russ -Allbery E<lt>rra@stanford.eduE<gt>. - -=cut diff --git a/contrib/perl5/lib/Pod/Text/Termcap.pm b/contrib/perl5/lib/Pod/Text/Termcap.pm deleted file mode 100644 index 333852a..0000000 --- a/contrib/perl5/lib/Pod/Text/Termcap.pm +++ /dev/null @@ -1,145 +0,0 @@ -# Pod::Text::Termcap -- Convert POD data to ASCII text with format escapes. -# $Id: Termcap.pm,v 1.0 2000/12/25 12:52:48 eagle Exp $ -# -# Copyright 1999 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 is a simple subclass of Pod::Text that overrides a few key methods to -# output the right termcap escape sequences for formatted text on the -# current terminal type. - -############################################################################ -# Modules and declarations -############################################################################ - -package Pod::Text::Termcap; - -require 5.004; - -use Pod::Text (); -use POSIX (); -use Term::Cap; - -use strict; -use vars qw(@ISA $VERSION); - -@ISA = qw(Pod::Text); - -# Don't use the CVS revision as the version, since this module is also in -# Perl core and too many things could munge CVS magic revision strings. -# This number should ideally be the same as the CVS revision in podlators, -# however. -$VERSION = 1.00; - - -############################################################################ -# Overrides -############################################################################ - -# In the initialization method, grab our terminal characteristics as well as -# do all the stuff we normally do. -sub initialize { - my $self = shift; - - # The default Term::Cap path won't work on Solaris. - $ENV{TERMPATH} = "$ENV{HOME}/.termcap:/etc/termcap" - . ":/usr/share/misc/termcap:/usr/share/lib/termcap"; - - my $termios = POSIX::Termios->new; - $termios->getattr; - my $ospeed = $termios->getospeed; - my $term = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed }; - $$self{BOLD} = $$term{_md} or die 'BOLD'; - $$self{UNDL} = $$term{_us} or die 'UNDL'; - $$self{NORM} = $$term{_me} or die 'NORM'; - - unless (defined $$self{width}) { - $$self{width} = $ENV{COLUMNS} || $$term{_co} || 78; - $$self{width} -= 2; - } - - $self->SUPER::initialize; -} - -# Make level one headings bold. -sub cmd_head1 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $self->SUPER::cmd_head1 ("$$self{BOLD}$_$$self{NORM}"); -} - -# Make level two headings bold. -sub cmd_head2 { - my $self = shift; - local $_ = shift; - s/\s+$//; - $self->SUPER::cmd_head2 ("$$self{BOLD}$_$$self{NORM}"); -} - -# Fix up B<> and I<>. Note that we intentionally don't do F<>. -sub seq_b { my $self = shift; return "$$self{BOLD}$_[0]$$self{NORM}" } -sub seq_i { my $self = shift; return "$$self{UNDL}$_[0]$$self{NORM}" } - -# Override the wrapping code to igore the special sequences. -sub wrap { - my $self = shift; - local $_ = shift; - my $output = ''; - my $spaces = ' ' x $$self{MARGIN}; - my $width = $$self{width} - $$self{MARGIN}; - my $code = "(?:\Q$$self{BOLD}\E|\Q$$self{UNDL}\E|\Q$$self{NORM}\E)"; - while (length > $width) { - if (s/^((?:$code?[^\n]){0,$width})\s+// - || s/^((?:$code?[^\n]){$width})//) { - $output .= $spaces . $1 . "\n"; - } else { - last; - } - } - $output .= $spaces . $_; - $output =~ s/\s+$/\n\n/; - $output; -} - - -############################################################################ -# Module return value and documentation -############################################################################ - -1; -__END__ - -=head1 NAME - -Pod::Text::Color - Convert POD data to ASCII text with format escapes - -=head1 SYNOPSIS - - use Pod::Text::Termcap; - my $parser = Pod::Text::Termcap->new (sentence => 0, width => 78); - - # Read POD from STDIN and write to STDOUT. - $parser->parse_from_filehandle; - - # Read POD from file.pod and write to file.txt. - $parser->parse_from_file ('file.pod', 'file.txt'); - -=head1 DESCRIPTION - -Pod::Text::Termcap is a simple subclass of Pod::Text that highlights output -text using the correct termcap escape sequences for the current terminal. -Apart from the format codes, it in all ways functions like Pod::Text. See -L<Pod::Text> for details and available options. - -=head1 SEE ALSO - -L<Pod::Text|Pod::Text>, L<Pod::Parser|Pod::Parser> - -=head1 AUTHOR - -Russ Allbery E<lt>rra@stanford.eduE<gt>. - -=cut diff --git a/contrib/perl5/lib/Pod/Usage.pm b/contrib/perl5/lib/Pod/Usage.pm deleted file mode 100644 index 3886076..0000000 --- a/contrib/perl5/lib/Pod/Usage.pm +++ /dev/null @@ -1,559 +0,0 @@ -############################################################################# -# Pod/Usage.pm -- print usage messages for the running script. -# -# 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::Usage; - -use vars qw($VERSION); -$VERSION = 1.14; ## Current version of this package -require 5.005; ## requires this Perl version or later - -=head1 NAME - -Pod::Usage, pod2usage() - print a usage message from embedded pod documentation - -=head1 SYNOPSIS - - use Pod::Usage - - my $message_text = "This text precedes the usage message."; - my $exit_status = 2; ## The exit status to use - my $verbose_level = 0; ## The verbose level to use - my $filehandle = \*STDERR; ## The filehandle to write to - - pod2usage($message_text); - - pod2usage($exit_status); - - pod2usage( { -message => $message_text , - -exitval => $exit_status , - -verbose => $verbose_level, - -output => $filehandle } ); - - pod2usage( -msg => $message_text , - -exitval => $exit_status , - -verbose => $verbose_level, - -output => $filehandle ); - -=head1 ARGUMENTS - -B<pod2usage> should be given either a single argument, or a list of -arguments corresponding to an associative array (a "hash"). When a single -argument is given, it should correspond to exactly one of the following: - -=over 4 - -=item * - -A string containing the text of a message to print I<before> printing -the usage message - -=item * - -A numeric value corresponding to the desired exit status - -=item * - -A reference to a hash - -=back - -If more than one argument is given then the entire argument list is -assumed to be a hash. If a hash is supplied (either as a reference or -as a list) it should contain one or more elements with the following -keys: - -=over 4 - -=item C<-message> - -=item C<-msg> - -The text of a message to print immediately prior to printing the -program's usage message. - -=item C<-exitval> - -The desired exit status to pass to the B<exit()> function. -This should be an integer, or else the string "NOEXIT" to -indicate that control should simply be returned without -terminating the invoking process. - -=item C<-verbose> - -The desired level of "verboseness" to use when printing the usage -message. If the corresponding value is 0, then only the "SYNOPSIS" -section of the pod documentation is printed. If the corresponding value -is 1, then the "SYNOPSIS" section, along with any section entitled -"OPTIONS", "ARGUMENTS", or "OPTIONS AND ARGUMENTS" is printed. If the -corresponding value is 2 or more then the entire manpage is printed. - -=item C<-output> - -A reference to a filehandle, or the pathname of a file to which the -usage message should be written. The default is C<\*STDERR> unless the -exit value is less than 2 (in which case the default is C<\*STDOUT>). - -=item C<-input> - -A reference to a filehandle, or the pathname of a file from which the -invoking script's pod documentation should be read. It defaults to the -file indicated by C<$0> (C<$PROGRAM_NAME> for users of F<English.pm>). - -=item C<-pathlist> - -A list of directory paths. If the input file does not exist, then it -will be searched for in the given directory list (in the order the -directories appear in the list). It defaults to the list of directories -implied by C<$ENV{PATH}>. The list may be specified either by a reference -to an array, or by a string of directory paths which use the same path -separator as C<$ENV{PATH}> on your system (e.g., C<:> for Unix, C<;> for -MSWin32 and DOS). - -=back - -=head1 DESCRIPTION - -B<pod2usage> will print a usage message for the invoking script (using -its embedded pod documentation) and then exit the script with the -desired exit status. The usage message printed may have any one of three -levels of "verboseness": If the verbose level is 0, then only a synopsis -is printed. If the verbose level is 1, then the synopsis is printed -along with a description (if present) of the command line options and -arguments. If the verbose level is 2, then the entire manual page is -printed. - -Unless they are explicitly specified, the default values for the exit -status, verbose level, and output stream to use are determined as -follows: - -=over 4 - -=item * - -If neither the exit status nor the verbose level is specified, then the -default is to use an exit status of 2 with a verbose level of 0. - -=item * - -If an exit status I<is> specified but the verbose level is I<not>, then the -verbose level will default to 1 if the exit status is less than 2 and -will default to 0 otherwise. - -=item * - -If an exit status is I<not> specified but verbose level I<is> given, then -the exit status will default to 2 if the verbose level is 0 and will -default to 1 otherwise. - -=item * - -If the exit status used is less than 2, then output is printed on -C<STDOUT>. Otherwise output is printed on C<STDERR>. - -=back - -Although the above may seem a bit confusing at first, it generally does -"the right thing" in most situations. This determination of the default -values to use is based upon the following typical Unix conventions: - -=over 4 - -=item * - -An exit status of 0 implies "success". For example, B<diff(1)> exits -with a status of 0 if the two files have the same contents. - -=item * - -An exit status of 1 implies possibly abnormal, but non-defective, program -termination. For example, B<grep(1)> exits with a status of 1 if -it did I<not> find a matching line for the given regular expression. - -=item * - -An exit status of 2 or more implies a fatal error. For example, B<ls(1)> -exits with a status of 2 if you specify an illegal (unknown) option on -the command line. - -=item * - -Usage messages issued as a result of bad command-line syntax should go -to C<STDERR>. However, usage messages issued due to an explicit request -to print usage (like specifying B<-help> on the command line) should go -to C<STDOUT>, just in case the user wants to pipe the output to a pager -(such as B<more(1)>). - -=item * - -If program usage has been explicitly requested by the user, it is often -desireable to exit with a status of 1 (as opposed to 0) after issuing -the user-requested usage message. It is also desireable to give a -more verbose description of program usage in this case. - -=back - -B<pod2usage> doesn't force the above conventions upon you, but it will -use them by default if you don't expressly tell it to do otherwise. The -ability of B<pod2usage()> to accept a single number or a string makes it -convenient to use as an innocent looking error message handling function: - - use Pod::Usage; - use Getopt::Long; - - ## Parse options - GetOptions("help", "man", "flag1") || pod2usage(2); - pod2usage(1) if ($opt_help); - pod2usage(-verbose => 2) if ($opt_man); - - ## Check for too many filenames - pod2usage("$0: Too many files given.\n") if (@ARGV > 1); - -Some user's however may feel that the above "economy of expression" is -not particularly readable nor consistent and may instead choose to do -something more like the following: - - use Pod::Usage; - use Getopt::Long; - - ## Parse options - GetOptions("help", "man", "flag1") || pod2usage(-verbose => 0); - pod2usage(-verbose => 1) if ($opt_help); - pod2usage(-verbose => 2) if ($opt_man); - - ## Check for too many filenames - pod2usage(-verbose => 2, -message => "$0: Too many files given.\n") - if (@ARGV > 1); - -As with all things in Perl, I<there's more than one way to do it>, and -B<pod2usage()> adheres to this philosophy. If you are interested in -seeing a number of different ways to invoke B<pod2usage> (although by no -means exhaustive), please refer to L<"EXAMPLES">. - -=head1 EXAMPLES - -Each of the following invocations of C<pod2usage()> will print just the -"SYNOPSIS" section to C<STDERR> and will exit with a status of 2: - - pod2usage(); - - pod2usage(2); - - pod2usage(-verbose => 0); - - pod2usage(-exitval => 2); - - pod2usage({-exitval => 2, -output => \*STDERR}); - - pod2usage({-verbose => 0, -output => \*STDERR}); - - pod2usage(-exitval => 2, -verbose => 0); - - pod2usage(-exitval => 2, -verbose => 0, -output => \*STDERR); - -Each of the following invocations of C<pod2usage()> will print a message -of "Syntax error." (followed by a newline) to C<STDERR>, immediately -followed by just the "SYNOPSIS" section (also printed to C<STDERR>) and -will exit with a status of 2: - - pod2usage("Syntax error."); - - pod2usage(-message => "Syntax error.", -verbose => 0); - - pod2usage(-msg => "Syntax error.", -exitval => 2); - - pod2usage({-msg => "Syntax error.", -exitval => 2, -output => \*STDERR}); - - pod2usage({-msg => "Syntax error.", -verbose => 0, -output => \*STDERR}); - - pod2usage(-msg => "Syntax error.", -exitval => 2, -verbose => 0); - - pod2usage(-message => "Syntax error.", - -exitval => 2, - -verbose => 0, - -output => \*STDERR); - -Each of the following invocations of C<pod2usage()> will print the -"SYNOPSIS" section and any "OPTIONS" and/or "ARGUMENTS" sections to -C<STDOUT> and will exit with a status of 1: - - pod2usage(1); - - pod2usage(-verbose => 1); - - pod2usage(-exitval => 1); - - pod2usage({-exitval => 1, -output => \*STDOUT}); - - pod2usage({-verbose => 1, -output => \*STDOUT}); - - pod2usage(-exitval => 1, -verbose => 1); - - pod2usage(-exitval => 1, -verbose => 1, -output => \*STDOUT}); - -Each of the following invocations of C<pod2usage()> will print the -entire manual page to C<STDOUT> and will exit with a status of 1: - - pod2usage(-verbose => 2); - - pod2usage({-verbose => 2, -output => \*STDOUT}); - - pod2usage(-exitval => 1, -verbose => 2); - - pod2usage({-exitval => 1, -verbose => 2, -output => \*STDOUT}); - -=head2 Recommended Use - -Most scripts should print some type of usage message to C<STDERR> when a -command line syntax error is detected. They should also provide an -option (usually C<-H> or C<-help>) to print a (possibly more verbose) -usage message to C<STDOUT>. Some scripts may even wish to go so far as to -provide a means of printing their complete documentation to C<STDOUT> -(perhaps by allowing a C<-man> option). The following complete example -uses B<Pod::Usage> in combination with B<Getopt::Long> to do all of these -things: - - use Getopt::Long; - use Pod::Usage; - - my $man = 0; - my $help = 0; - ## Parse options and print usage if there is a syntax error, - ## or if usage was explicitly requested. - GetOptions('help|?' => \$help, man => \$man) or pod2usage(2); - pod2usage(1) if $help; - pod2usage(-verbose => 2) if $man; - - ## If no arguments were given, then allow STDIN to be used only - ## if it's not connected to a terminal (otherwise print usage) - pod2usage("$0: No files given.") if ((@ARGV == 0) && (-t STDIN)); - __END__ - - =head1 NAME - - sample - Using GetOpt::Long and Pod::Usage - - =head1 SYNOPSIS - - sample [options] [file ...] - - Options: - -help brief help message - -man full documentation - - =head1 OPTIONS - - =over 8 - - =item B<-help> - - Print a brief help message and exits. - - =item B<-man> - - Prints the manual page and exits. - - =back - - =head1 DESCRIPTION - - B<This program> will read the given input file(s) and do something - useful with the contents thereof. - - =cut - -=head1 CAVEATS - -By default, B<pod2usage()> will use C<$0> as the path to the pod input -file. Unfortunately, not all systems on which Perl runs will set C<$0> -properly (although if C<$0> isn't found, B<pod2usage()> will search -C<$ENV{PATH}> or else the list specified by the C<-pathlist> option). -If this is the case for your system, you may need to explicitly specify -the path to the pod docs for the invoking script using something -similar to the following: - - pod2usage(-exitval => 2, -input => "/path/to/your/pod/docs"); - -=head1 AUTHOR - -Brad Appleton E<lt>bradapp@enteract.comE<gt> - -Based on code for B<Pod::Text::pod2text()> written by -Tom Christiansen E<lt>tchrist@mox.perl.comE<gt> - -=head1 ACKNOWLEDGEMENTS - -Steven McDougall E<lt>swmcd@world.std.comE<gt> for his help and patience -with re-writing this manpage. - -=cut - -############################################################################# - -use strict; -#use diagnostics; -use Carp; -use Config; -use Exporter; -use File::Spec; - -use vars qw(@ISA @EXPORT); -@EXPORT = qw(&pod2usage); -BEGIN { - if ( $] >= 5.005_58 ) { - require Pod::Text; - @ISA = qw( Pod::Text ); - } - else { - require Pod::PlainText; - @ISA = qw( Pod::PlainText ); - } -} - - -##--------------------------------------------------------------------------- - -##--------------------------------- -## Function definitions begin here -##--------------------------------- - -sub pod2usage { - local($_) = shift || ""; - my %opts; - ## Collect arguments - if (@_ > 0) { - ## Too many arguments - assume that this is a hash and - ## the user forgot to pass a reference to it. - %opts = ($_, @_); - } - elsif (ref $_) { - ## User passed a ref to a hash - %opts = %{$_} if (ref($_) eq 'HASH'); - } - elsif (/^[-+]?\d+$/) { - ## User passed in the exit value to use - $opts{"-exitval"} = $_; - } - else { - ## User passed in a message to print before issuing usage. - $_ and $opts{"-message"} = $_; - } - - ## Need this for backward compatibility since we formerly used - ## options that were all uppercase words rather than ones that - ## looked like Unix command-line options. - ## to be uppercase keywords) - %opts = map { - my $val = $opts{$_}; - s/^(?=\w)/-/; - /^-msg/i and $_ = '-message'; - /^-exit/i and $_ = '-exitval'; - lc($_) => $val; - } (keys %opts); - - ## Now determine default -exitval and -verbose values to use - if ((! defined $opts{"-exitval"}) && (! defined $opts{"-verbose"})) { - $opts{"-exitval"} = 2; - $opts{"-verbose"} = 0; - } - elsif (! defined $opts{"-exitval"}) { - $opts{"-exitval"} = ($opts{"-verbose"} > 0) ? 1 : 2; - } - elsif (! defined $opts{"-verbose"}) { - $opts{"-verbose"} = ($opts{"-exitval"} < 2); - } - - ## Default the output file - $opts{"-output"} = ($opts{"-exitval"} < 2) ? \*STDOUT : \*STDERR - unless (defined $opts{"-output"}); - ## Default the input file - $opts{"-input"} = $0 unless (defined $opts{"-input"}); - - ## Look up input file in path if it doesnt exist. - unless ((ref $opts{"-input"}) || (-e $opts{"-input"})) { - my ($dirname, $basename) = ('', $opts{"-input"}); - my $pathsep = ($^O =~ /^(?:dos|os2|MSWin32)$/) ? ";" - : (($^O eq 'MacOS') ? ',' : ":"); - my $pathspec = $opts{"-pathlist"} || $ENV{PATH} || $ENV{PERL5LIB}; - - my @paths = (ref $pathspec) ? @$pathspec : split($pathsep, $pathspec); - for $dirname (@paths) { - $_ = File::Spec->catfile($dirname, $basename) if length; - last if (-e $_) && ($opts{"-input"} = $_); - } - } - - ## Now create a pod reader and constrain it to the desired sections. - my $parser = new Pod::Usage(USAGE_OPTIONS => \%opts); - if ($opts{"-verbose"} == 0) { - $parser->select("SYNOPSIS"); - } - elsif ($opts{"-verbose"} == 1) { - my $opt_re = '(?i)' . - '(?:OPTIONS|ARGUMENTS)' . - '(?:\s*(?:AND|\/)\s*(?:OPTIONS|ARGUMENTS))?'; - $parser->select( 'SYNOPSIS', $opt_re, "DESCRIPTION/$opt_re" ); - } - - ## Now translate the pod document and then exit with the desired status - if ( $opts{"-verbose"} >= 2 - and !ref($opts{"-input"}) - and $opts{"-output"} == \*STDOUT ) - { - ## spit out the entire PODs. Might as well invoke perldoc - my $progpath = File::Spec->catfile($Config{bin}, "perldoc"); - system($progpath, $opts{"-input"}); - } - else { - $parser->parse_from_file($opts{"-input"}, $opts{"-output"}); - } - - exit($opts{"-exitval"}) unless (lc($opts{"-exitval"}) eq 'noexit'); -} - -##--------------------------------------------------------------------------- - -##------------------------------- -## Method definitions begin here -##------------------------------- - -sub new { - my $this = shift; - my $class = ref($this) || $this; - my %params = @_; - my $self = {%params}; - bless $self, $class; - $self->initialize(); - return $self; -} - -sub begin_pod { - my $self = shift; - $self->SUPER::begin_pod(); ## Have to call superclass - my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1; - my $out_fh = $self->output_handle(); - print $out_fh "$msg\n"; -} - -sub preprocess_paragraph { - my $self = shift; - local $_ = shift; - my $line = shift; - ## See if this is a heading and we arent printing the entire manpage. - if (($self->{USAGE_OPTIONS}->{-verbose} < 2) && /^=head/) { - ## Change the title of the SYNOPSIS section to USAGE - s/^=head1\s+SYNOPSIS\s*$/=head1 USAGE/; - ## Try to do some lowercasing instead of all-caps in headings - s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge; - ## Use a colon to end all headings - s/\s*$/:/ unless (/:\s*$/); - $_ .= "\n"; - } - return $self->SUPER::preprocess_paragraph($_); -} - |