From 3c01495985c7c4b8f1b95ec88b49209869fdb517 Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Tue, 10 Jul 2001 13:16:11 +0000 Subject: [PATCH] Upgrade to podlators 1.10. p4raw-id: //depot/perl@11255 --- lib/Pod/Man.pm | 345 +++++++++++++++++++++++++-------------------- lib/Pod/Text.pm | 176 ++++++++++++++--------- lib/Pod/Text/Color.pm | 40 +++--- lib/Pod/Text/Overstrike.pm | 36 +++-- lib/Pod/Text/Termcap.pm | 38 ++--- pod/pod2man.PL | 47 +++--- pod/pod2text.PL | 11 +- 7 files changed, 400 insertions(+), 293 deletions(-) diff --git a/lib/Pod/Man.pm b/lib/Pod/Man.pm index af93b2e..669e04b 100644 --- a/lib/Pod/Man.pm +++ b/lib/Pod/Man.pm @@ -1,25 +1,25 @@ # Pod::Man -- Convert POD data to formatted *roff input. -# $Id: Man.pm,v 1.16 2001/04/09 13:06:02 eagle Exp $ +# $Id: Man.pm,v 1.19 2001/07/10 11:08:09 eagle Exp $ # # Copyright 1999, 2000, 2001 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may 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. +# 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; @@ -34,23 +34,21 @@ 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.16; +# 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.19; -############################################################################ +############################################################################## # 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\@//g before -# output. +# quotes to use for C<> text, designated by @LQOUTE@ and @RQUOTE@. $PREAMBLE +# should therefore be run through s/\@CFONT\@//g before output. $PREAMBLE = <<'----END OF PREAMBLE----'; .de Sh \" Subsection heading .br @@ -64,12 +62,6 @@ $PREAMBLE = <<'----END OF PREAMBLE----'; .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 @@ -83,9 +75,9 @@ $PREAMBLE = <<'----END OF PREAMBLE----'; .\" 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<> +.\" 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 \{\ @@ -105,10 +97,10 @@ $PREAMBLE = <<'----END OF PREAMBLE----'; . 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 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" @@ -117,8 +109,8 @@ $PREAMBLE = <<'----END OF PREAMBLE----'; . rr F .\} .\" -.\" For nroff, turn off justification. Always turn off hyphenation; it -.\" makes way too many mistakes in technical documents. +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. .hy 0 .if n .na .\" @@ -264,14 +256,14 @@ $PREAMBLE = <<'----END OF PREAMBLE----'; ); -############################################################################ +############################################################################## # 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. +# 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; @@ -282,21 +274,21 @@ sub protect { 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(). +############################################################################## + +# 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. + # 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) { @@ -308,15 +300,15 @@ sub initialize { } } - # Set the default fonts. We can't be sure what fixed bold-italic is - # going to be called, so default to just bold. + # 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. + # 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}), @@ -329,10 +321,10 @@ sub initialize { 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. + # 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; @@ -360,9 +352,9 @@ sub initialize { 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. + # 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/\"/\"\"/; @@ -393,8 +385,8 @@ sub begin_pod { # */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. + # 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 @@ -409,8 +401,8 @@ sub begin_pod { } } - # If $name contains spaces, quote it; this mostly comes up in the case - # of input from stdin. + # 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 @@ -434,9 +426,9 @@ sub begin_pod { .\\" @{[ scalar localtime ]} .\\" .\\" Standard preamble: -.\\" ====================================================================== +.\\" ======================================================================== $_ -.\\" ====================================================================== +.\\" ======================================================================== .\\" .IX Title "$name $section" .TH $name $section "$$self{release}" "$$self{date}" "$$self{center}" @@ -450,9 +442,9 @@ $_ } -############################################################################ +############################################################################## # Core overrides -############################################################################ +############################################################################## # Called for each command paragraph. Gets the command, the associated # paragraph, the line number, and a Pod::Paragraph object. Just dispatches @@ -462,11 +454,11 @@ sub command { my $self = shift; my $command = shift; return if $command eq 'pod'; - return if ($$self{EXCLUDE} && $command ne 'end'); + return if ($$self{EXCLUDE} && $command ne 'end'); if ($self->can ('cmd_' . $command)) { $command = 'cmd_' . $command; $self->$command (@_); - } else { + } else { my ($text, $line, $paragraph) = @_; my $file; ($file, $line) = $paragraph->file_line; @@ -477,10 +469,10 @@ sub command { } } -# 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. +# 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}; @@ -496,16 +488,16 @@ sub verbatim { $$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. +# 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. + # 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. @@ -551,8 +543,8 @@ sub textblock { # 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. +# 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; @@ -593,8 +585,9 @@ sub sequence { } 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'; + # A bug in lvalue subs in 5.6 requires the temporary variable. + my $tmp = $self->quote_literal ($_); + return bless \ "$tmp", 'Pod::Man::String'; } # Handle links. @@ -618,16 +611,15 @@ sub sequence { } -############################################################################ +############################################################################## # 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. +# already uses small caps, so remove any E<> sequences that would cause them. sub cmd_head1 { my $self = shift; local $_ = $self->parse (@_); @@ -727,10 +719,9 @@ sub cmd_back { # 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. +# 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 (@_); @@ -748,7 +739,7 @@ sub cmd_item { } $_ = $self->textmapfonts ($_); $self->output (".PD 0\n") if ($$self{ITEMS} == 1); - $self->output ($self->switchquotes ('.Ip', $_, $$self{INDENT})); + $self->output ($self->switchquotes ('.IP', $_, $$self{INDENT})); $self->outindex ($index ? ('Item', $index) : ()); $$self{NEEDSPACE} = 0; $$self{ITEMS}++; @@ -785,9 +776,9 @@ sub cmd_for { } -############################################################################ +############################################################################## # 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. @@ -805,16 +796,15 @@ sub buildlink { s/^\s+//; s/\s+$//; - # If the argument looks like a URL, return it verbatim. This only - # handles URLs that use the server syntax. + # 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 forces a manpage interpretation, as does - # something looking like L. Do the same thing to - # L 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. + # Default to using the whole content of the link entry as a section name. + # Note that L forces a manpage interpretation, as does something + # looking like L. Do the same to L 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 . '"'; @@ -852,23 +842,23 @@ sub buildlink { } -############################################################################ +############################################################################## # Escaping and fontification -############################################################################ +############################################################################## # At this point, we'll have embedded font codes of the form \f([SE] -# where is one of B, I, or F. Turn those into the right font start -# or end codes. The old pod2man didn't get B 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. +# where is one of B, I, or F. Turn those into the right font start or +# end codes. The old pod2man didn't get B 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. +# 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; @@ -895,9 +885,9 @@ sub mapfonts { # 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. +# 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; @@ -912,9 +902,9 @@ sub textmapfonts { } -############################################################################ -# *roff-specific parsing -############################################################################ +############################################################################## +# *roff-specific parsing and magic +############################################################################## # Called instead of parse_text, calls parse_text with the right flags. sub parse { @@ -924,13 +914,13 @@ sub parse { } # 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, +# 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. +# 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) { @@ -952,8 +942,7 @@ sub collapse { } # Takes a text block to perform guesswork on; this is guaranteed not to -# contain any interior sequences. Returns the text block with remapping -# done. +# contain any interior sequences. Returns the text block with remapping done. sub guesswork { my $self = shift; local $_ = shift; @@ -964,8 +953,8 @@ sub guesswork { # 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 + # 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\(\"\'\`\[\{<>] ) @@ -973,9 +962,6 @@ sub guesswork { (?: (?= [\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 | \\s-1 ) @@ -1028,10 +1014,42 @@ sub guesswork { $_; } +# Handles C<> text, deciding whether to put \*C` around it or not. This is a +# whole bunch of messy heuristics to try to avoid overquoting, originally from +# Barrie Slaymaker. This largely duplicates similar code in Pod::Text. +sub quote_literal { + my $self = shift; + local $_ = shift; + + # A regex that matches the portion of a variable reference that's the + # array or hash index, separated out just because we want to use it in + # several places in the following regex. + my $index = '(?: \[.*\] | \{.*\} )?'; + + # Check for things that we don't want to quote, and if we find any of + # them, return the string with just a font change and no quoting. + m{ + ^\s* + (?: + ( [\'\`\"] ) .* \1 # already quoted + | \` .* \' # `quoted' + | \$+ [\#^]? \S $index # special ($^Foo, $") + | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func + | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call + | [+-]? [\d.]+ (?: [eE] [+-]? \d+ )? # a number + | 0x [a-fA-F\d]+ # a hex constant + ) + \s*\z + }xo && return '\f(FS' . $_ . '\f(FE'; + + # If we didn't return, go ahead and quote the text. + return '\f(FS\*(C`' . $_ . "\\*(C'\\f(FE"; +} + -############################################################################ +############################################################################## # Output formatting -############################################################################ +############################################################################## # Make vertical whitespace. sub makespace { @@ -1042,9 +1060,9 @@ sub makespace { 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. +# 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} }; @@ -1084,22 +1102,39 @@ sub switchquotes { # 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. + # 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 because it passes + # the argument off to .TP. my $c_is_quote = ($$self{LQUOTE} =~ /\"/) || ($$self{RQUOTE} =~ /\"/); - if (/\"/ || ($c_is_quote && /\\\*\(C[\'\`]/)) { + if (/\"/ || /\\f\(CW/) { s/\"/\"\"/g; + my $nroff = $_; 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" : ''); + if ($c_is_quote && /\\\*\(C[\'\`]/) { + $nroff =~ s/\\\*\(C\`/$$self{LQUOTE}/g; + $nroff =~ s/\\\*\(C\'/$$self{RQUOTE}/g; + $troff =~ s/\\\*\(C[\'\`]//g; + } + $nroff = qq("$nroff") . ($extra ? " $extra" : ''); $troff = qq("$troff") . ($extra ? " $extra" : ''); - return ".if n $command $_\n.el $command $troff\n"; + + # Work around the Solaris nroff bug where \f(CW\fP leaves the font set + # to Roman rather than the actual previous font when used in headings. + # troff output may still be broken, but at least we can fix nroff by + # just stripping out the font changes since fixed-width fonts don't + # mean anything for nroff. While we're at it, also remove the font + # changes for nroff in =item tags, since they're unnecessary. + $nroff =~ s/\\f\(CW(.*)\\f[PR]/$1/g; + + # Now finally output the command. Only bother with .if if the nroff + # and troff output isn't the same. + if ($nroff ne $troff) { + return ".if n $command $nroff\n.el $command $troff\n"; + } else { + return "$command $nroff\n"; + } } else { $_ = qq("$_") . ($extra ? " $extra" : ''); return "$command $_\n"; @@ -1138,9 +1173,9 @@ __END__ . ds Oe OE .\} -############################################################################ +############################################################################## # Documentation -############################################################################ +############################################################################## =head1 NAME @@ -1319,11 +1354,6 @@ know about. C%sE> was printed verbatim in the output. (W) The POD source contained a non-standard interior sequence (something of the form CE>) 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 @@ -1383,4 +1413,11 @@ the conventions. Russ Allbery Erra@stanford.eduE, based I heavily on the original B by Tom Christiansen Etchrist@mox.perl.comE. +=head1 COPYRIGHT AND LICENSE + +Copyright 1999, 2000, 2001 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + =cut diff --git a/lib/Pod/Text.pm b/lib/Pod/Text.pm index a0dab2d..9ebca63 100644 --- a/lib/Pod/Text.pm +++ b/lib/Pod/Text.pm @@ -1,19 +1,24 @@ # Pod::Text -- Convert POD data to formatted ASCII text. -# $Id: Text.pm,v 2.9 2001/04/09 13:00:50 eagle Exp $ +# $Id: Text.pm,v 2.11 2001/07/10 11:08:10 eagle Exp $ # # Copyright 1999, 2000, 2001 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may 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. +# This module replaces the old Pod::Text that came with versions of Perl prior +# to 5.6.0, 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. +# +# 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::Text; @@ -26,28 +31,27 @@ 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. +# 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.09; +# 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.11; -############################################################################ +############################################################################## # 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. +# 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 @@ -158,9 +162,9 @@ $VERSION = 2.09; ); -############################################################################ +############################################################################## # Initialization -############################################################################ +############################################################################## # Initialize the object. Must be sure to call our parent initializer. sub initialize { @@ -193,9 +197,9 @@ sub initialize { } -############################################################################ +############################################################################## # Core overrides -############################################################################ +############################################################################## # Called for each command paragraph. Gets the command, the associated # paragraph, the line number, and a Pod::Paragraph object. Just dispatches @@ -221,9 +225,9 @@ sub command { } } -# 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. +# 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}; @@ -234,8 +238,8 @@ sub verbatim { $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. +# 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}; @@ -294,8 +298,8 @@ sub textblock { # 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. +# 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; @@ -343,9 +347,9 @@ sub preprocess_paragraph { } -############################################################################ +############################################################################## # Command paragraphs -############################################################################ +############################################################################## # All command paragraphs take the paragraph and the line number. @@ -462,17 +466,46 @@ sub cmd_for { } -############################################################################ +############################################################################## # 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] . '*' } + +# Apply a whole bunch of messy heuristics to not quote things that don't +# benefit from being quoted. These originally come from Barrie Slaymaker and +# largely duplicate code in Pod::Man. sub seq_c { - return $_[0]{alt} ? "``$_[1]''" : "$_[0]{LQUOTE}$_[1]$_[0]{RQUOTE}" + my $self = shift; + local $_ = shift; + + # A regex that matches the portion of a variable reference that's the + # array or hash index, separated out just because we want to use it in + # several places in the following regex. + my $index = '(?: \[.*\] | \{.*\} )?'; + + # Check for things that we don't want to quote, and if we find any of + # them, return the string with just a font change and no quoting. + m{ + ^\s* + (?: + ( [\'\`\"] ) .* \1 # already quoted + | \` .* \' # `quoted' + | \$+ [\#^]? \S $index # special ($^Foo, $") + | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func + | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call + | [+-]? [\d.]+ (?: [eE] [+-]? \d+ )? # a number + | 0x [a-fA-F\d]+ # a hex constant + ) + \s*\z + }xo && return $_; + + # If we didn't return, go ahead and quote the text. + return $$self{alt} ? "``$_''" : "$$self{LQUOTE}$_$$self{RQUOTE}"; } # The complicated one. Handle links. Since this is plain text, we can't @@ -492,14 +525,14 @@ sub seq_l { s/^\s+//; s/\s+$//; - # If the argument looks like a URL, return it verbatim. This only - # handles URLs that use the server syntax. + # 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 forces a manpage interpretation, as does - # something looking like L. The latter is an - # enhancement over the original Pod::Text. + # Default to using the whole content of the link entry as a section name. + # Note that L forces a manpage interpretation, as does something + # looking like L. The latter is an enhancement over the + # original Pod::Text. my ($manpage, $section) = ('', $_); if (/^"\s*(.*?)\s*"$/) { $section = '"' . $1 . '"'; @@ -527,17 +560,17 @@ sub seq_l { } -############################################################################ +############################################################################## # 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. +############################################################################## + +# 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; @@ -569,14 +602,14 @@ sub item { } -############################################################################ +############################################################################## # 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. +# 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; @@ -601,8 +634,8 @@ 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 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; @@ -618,9 +651,9 @@ sub reformat { 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. @@ -644,9 +677,9 @@ sub pod2text { 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. + # 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; @@ -662,9 +695,9 @@ sub pod2text { } -############################################################################ +############################################################################## # Module return value and documentation -############################################################################ +############################################################################## 1; __END__ @@ -824,4 +857,11 @@ original Pod::Text by Tom Christiansen Etchrist@mox.perl.comE and its conversion to Pod::Parser by Brad Appleton Ebradapp@enteract.comE. +=head1 COPYRIGHT AND LICENSE + +Copyright 1999, 2000, 2001 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + =cut diff --git a/lib/Pod/Text/Color.pm b/lib/Pod/Text/Color.pm index e943216..f747a96 100644 --- a/lib/Pod/Text/Color.pm +++ b/lib/Pod/Text/Color.pm @@ -1,18 +1,18 @@ # 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 $ +# $Id: Color.pm,v 1.0 2001/07/10 11:03:43 eagle Exp $ # # Copyright 1999 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may 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. +# 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; @@ -26,16 +26,15 @@ 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; +# 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 -############################################################################ +############################################################################## # Make level one headings bold. sub cmd_head1 { @@ -79,9 +78,9 @@ sub wrap { $output; } -############################################################################ +############################################################################## # Module return value and documentation -############################################################################ +############################################################################## 1; __END__ @@ -123,6 +122,13 @@ L, L =head1 AUTHOR -Russ Allbery Erra@stanford.eduE. +Russ Allbery . + +=head1 COPYRIGHT AND LICENSE + +Copyright 1999 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. =cut diff --git a/lib/Pod/Text/Overstrike.pm b/lib/Pod/Text/Overstrike.pm index c9f0789..be159f4 100644 --- a/lib/Pod/Text/Overstrike.pm +++ b/lib/Pod/Text/Overstrike.pm @@ -1,10 +1,10 @@ # Pod::Text::Overstrike -- Convert POD data to formatted overstrike text -# $Id: Overstrike.pm,v 1.1 2000/12/25 12:51:23 eagle Exp $ +# $Id: Overstrike.pm,v 1.2 2001/07/10 11:04:36 eagle Exp $ # # Created by Joe Smith 30-Nov-2000 # (based on Pod::Text::Color by Russ Allbery ) # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may redistribute it and/or modify it # under the same terms as Perl itself. # # This was written because the output from: @@ -18,9 +18,9 @@ # and because both Pod::Text::Color and Pod::Text::Termcap are not device # independent. -############################################################################ +############################################################################## # Modules and declarations -############################################################################ +############################################################################## package Pod::Text::Overstrike; @@ -33,16 +33,15 @@ 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; +# 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.02; -############################################################################ +############################################################################## # Overrides -############################################################################ +############################################################################## # Make level one headings bold, overridding any existing formatting. sub cmd_head1 { @@ -103,9 +102,9 @@ sub wrap { $output; } -############################################################################ +############################################################################## # Module return value and documentation -############################################################################ +############################################################################## 1; __END__ @@ -154,7 +153,14 @@ L, L =head1 AUTHOR -Joe Smith EJoe.Smith@inwap.comE, using the framework created by Russ -Allbery Erra@stanford.eduE. +Joe Smith , using the framework created by Russ Allbery +. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2000 by Joe Smith . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. =cut diff --git a/lib/Pod/Text/Termcap.pm b/lib/Pod/Text/Termcap.pm index 333852a..c49e2c3 100644 --- a/lib/Pod/Text/Termcap.pm +++ b/lib/Pod/Text/Termcap.pm @@ -1,18 +1,18 @@ # 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 $ +# $Id: Termcap.pm,v 1.1 2001/07/10 11:04:36 eagle Exp $ # # Copyright 1999 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may 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. +# output the right termcap escape sequences for formatted text on the current +# terminal type. -############################################################################ +############################################################################## # Modules and declarations -############################################################################ +############################################################################## package Pod::Text::Termcap; @@ -27,16 +27,15 @@ 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; +# 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 -############################################################################ +############################################################################## # In the initialization method, grab our terminal characteristics as well as # do all the stuff we normally do. @@ -105,9 +104,9 @@ sub wrap { } -############################################################################ +############################################################################## # Module return value and documentation -############################################################################ +############################################################################## 1; __END__ @@ -140,6 +139,13 @@ L, L =head1 AUTHOR -Russ Allbery Erra@stanford.eduE. +Russ Allbery . + +=head1 COPYRIGHT AND LICENSE + +Copyright 1999 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. =cut diff --git a/pod/pod2man.PL b/pod/pod2man.PL index 7a50fc5..cef507b 100644 --- a/pod/pod2man.PL +++ b/pod/pod2man.PL @@ -36,11 +36,11 @@ $Config{startperl} print OUT <<'!NO!SUBS!'; # pod2man -- Convert POD data to formatted *roff input. -# $Id: pod2man.PL,v 1.4 2000/11/19 05:47:46 eagle Exp $ +# $Id: pod2man.PL,v 1.6 2001/07/10 11:23:46 eagle Exp $ # -# Copyright 1999, 2000 by Russ Allbery +# Copyright 1999, 2000, 2001 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may redistribute it and/or modify it # under the same terms as Perl itself. require 5.004; @@ -57,8 +57,8 @@ use strict; my $stdin; @ARGV = map { $_ eq '-' && !$stdin++ ? ('--', $_) : $_ } @ARGV; -# Parse our options, trying to retain backwards compatibility with pod2man -# but allowing short forms as well. --lax is currently ignored. +# Parse our options, trying to retain backwards compatibility with pod2man but +# allowing short forms as well. --lax is currently ignored. my %options; Getopt::Long::config ('bundling_override'); GetOptions (\%options, 'section|s=s', 'release|r=s', 'center|c=s', @@ -72,15 +72,15 @@ if ($options{official} && !defined $options{center}) { $options{center} = 'Perl Programmers Reference Guide'; } -# Initialize and run the formatter, pulling a pair of input and output off -# at a time. +# Initialize and run the formatter, pulling a pair of input and output off at +# a time. my $parser = Pod::Man->new (%options); my @files; do { @files = splice (@ARGV, 0, 2); $parser->parse_from_file (@files); } while (@ARGV); - + __END__ =head1 NAME @@ -423,7 +423,8 @@ LEE, but other things in this section probably should be when appropriate. You may need to use the C...|...E> syntax to keep B and B from being too verbose; see perlpod(1). -If the package has a mailing list, include a URL here. +If the package has a mailing list, include a URL or subscription +instructions here. If the package has a web site, include a URL here. @@ -439,14 +440,14 @@ and pick an e-mail address that's likely to last if possible. For copyright - Copyright YEAR(s) by YOUR NAME(s) + Copyright YEAR(s) by YOUR NAME(s) (No, (C) is not needed. No, "all rights reserved" is not needed.) For licensing the easiest way is to use the same licensing as Perl itself: - This library is free software; you can redistribute it and/or modify - it under the same terms as Perl itself. + This library is free software; you may redistribute it and/or modify + it under the same terms as Perl itself. This makes it easy for people to use your module with Perl. Note that this licensing is neither an endorsement or a requirement, you are of @@ -454,8 +455,8 @@ course free to choose any licensing. =item HISTORY -Programs derived from other sources sometimes have this, or you might -keep a modification log here. If the log gets overly long or detailed, +Programs derived from other sources sometimes have this, or you might keep +a modification log here. If the log gets overly long or detailed, consider maintaining it in a separate file, though. =back @@ -467,10 +468,7 @@ of a C library. Documentation of object-oriented libraries or modules may use CONSTRUCTORS and METHODS sections for detailed documentation of the parts of the library and save the DESCRIPTION section for an overview; other large modules may use FUNCTIONS for similar reasons. Some people use -OVERVIEW to summarize the description if it's quite long. Sometimes there's -an additional COPYRIGHT section at the bottom, for licensing terms. -AVAILABILITY is sometimes added, giving the canonical download site for the -software or a URL for updates. +OVERVIEW to summarize the description if it's quite long. Section ordering varies, although NAME should I be the first section (you'll break some man page systems otherwise), and NAME, SYNOPSIS, @@ -501,11 +499,18 @@ your system. =head1 AUTHOR -Russ Allbery Erra@stanford.eduE, based I heavily on the -original B by Larry Wall and Tom Christiansen. Large portions of -this documentation, particularly the sections on the anatomy of a proper man +Russ Allbery , based I heavily on the original +B by Larry Wall and Tom Christiansen. Large portions of this +documentation, particularly the sections on the anatomy of a proper man page, are taken from the B documentation by Tom. +=head1 COPYRIGHT AND LICENSE + +Copyright 1999, 2000, 2001 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + =cut !NO!SUBS! #'# (cperl-mode) diff --git a/pod/pod2text.PL b/pod/pod2text.PL index 7b5727d..54a2279 100644 --- a/pod/pod2text.PL +++ b/pod/pod2text.PL @@ -39,7 +39,7 @@ print OUT <<'!NO!SUBS!'; # # Copyright 1999, 2000 by Russ Allbery # -# This program is free software; you can redistribute it and/or modify it +# This program is free software; you may redistribute it and/or modify it # under the same terms as Perl itself. # # The driver script for Pod::Text, Pod::Text::Termcap, and Pod::Text::Color, @@ -243,7 +243,14 @@ L, L =head1 AUTHOR -Russ Allbery Erra@stanford.eduE. +Russ Allbery . + +=head1 COPYRIGHT AND LICENSE + +Copyright 1999, 2000, 2001 by Russ Allbery . + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. =cut !NO!SUBS! -- 2.7.4