summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2000-06-01 12:52:02 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2000-06-01 12:52:02 +0000
commit53fe373b05b06f68094ed67e5c78b4dda7f0d5b8 (patch)
tree916d54741a1c784c238e29c8b519f79e64a6a5a7
parente708dd94d433419cc9415d9e2faa486ad23ac459 (diff)
parent4ebbc97598d793d933009eab4334e3bc88b8de4e (diff)
downloadperl-53fe373b05b06f68094ed67e5c78b4dda7f0d5b8.tar.gz
Integrate with Sarathy.
p4raw-id: //depot/cfgperl@6192
-rw-r--r--AUTHORS1
-rw-r--r--MAINTAIN5
-rw-r--r--MANIFEST2
-rw-r--r--doop.c6
-rwxr-xr-xembed.pl2
-rw-r--r--ext/Devel/Peek/Peek.pm2
-rw-r--r--handy.h2
-rw-r--r--lib/Pod/LaTeX.pm1567
-rw-r--r--lib/SelfLoader.pm5
-rw-r--r--perl.c3
-rw-r--r--pod/perlapi.pod2
-rw-r--r--pod/perldata.pod3
-rw-r--r--pod/perlfaq6.pod3
-rw-r--r--pod/perlfaq9.pod3
-rw-r--r--pod/perlfunc.pod8
-rw-r--r--pod/perllocale.pod7
-rw-r--r--pod/perlre.pod7
-rw-r--r--pod/perltrap.pod6
-rw-r--r--pod/pod2latex.PL928
-rwxr-xr-xt/lib/selfloader.t198
-rwxr-xr-xt/op/tr.t26
-rwxr-xr-xt/op/vec.t12
-rw-r--r--utils/h2xs.PL4
23 files changed, 2128 insertions, 674 deletions
diff --git a/AUTHORS b/AUTHORS
index 912deddf6b..3032d48814 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -54,6 +54,7 @@ pueschel Norbert Pueschel pueschel@imsdd.meb.uni-bonn.de
pvhp Peter Prymmer pvhp@forte.com
raphael Raphael Manfredi Raphael_Manfredi@pobox.com
rdieter Rex Dieter rdieter@math.unl.edu
+rra Russ Allbery rra@stanford.edu
rsanders Robert Sanders Robert.Sanders@linux.org
roberto Ollivier Robert roberto@keltia.freenix.fr
roderick Roderick Schertler roderick@argon.org
diff --git a/MAINTAIN b/MAINTAIN
index ffdd077334..b2e370d14d 100644
--- a/MAINTAIN
+++ b/MAINTAIN
@@ -437,10 +437,13 @@ lib/Pod/Checker.pm bradapp
lib/Pod/Functions.pm
lib/Pod/Html.pm tchrist
lib/Pod/InputObjects.pm bradapp
+lib/Pod/LaTeX.pm tjenness
+lib/Pod/Man.pm rra
lib/Pod/Parser.pm bradapp
lib/Pod/PlainText.pm bradapp
lib/Pod/Select.pm bradapp
-lib/Pod/Text.pm tchrist
+lib/Pod/Text.pm rra
+lib/Pod/Text/* rra
lib/Pod/Usage.pm bradapp
lib/Search/Dict.pm
lib/SelectSaver.pm
diff --git a/MANIFEST b/MANIFEST
index e945d19e37..be991fb146 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -646,6 +646,7 @@ lib/Pod/Find.pm used by pod/splitpod
lib/Pod/Functions.pm used by pod/splitpod
lib/Pod/Html.pm Convert POD data to HTML
lib/Pod/InputObjects.pm Pod-Parser - define objects for input streams
+lib/Pod/LaTeX.pm Convert POD data to LaTeX
lib/Pod/Man.pm Convert POD data to *roff
lib/Pod/ParseUtils.pm Pod-Parser - pod utility functions
lib/Pod/Parser.pm Pod-Parser - define base class for parsing POD
@@ -1368,6 +1369,7 @@ t/lib/safe2.t See if Safe works
t/lib/sdbm.t See if SDBM_File works
t/lib/searchdict.t See if Search::Dict works
t/lib/selectsaver.t See if SelectSaver works
+t/lib/selfloader.t See if SelfLoader works
t/lib/socket.t See if Socket works
t/lib/soundex.t See if Soundex works
t/lib/symbol.t See if Symbol works
diff --git a/doop.c b/doop.c
index c79b435171..37f87e69df 100644
--- a/doop.c
+++ b/doop.c
@@ -592,7 +592,8 @@ Perl_do_trans(pTHX_ SV *sv)
return 0;
if (!SvPOKp(sv))
(void)SvPV_force(sv, len);
- (void)SvPOK_only(sv);
+ if (!(PL_op->op_private & OPpTRANS_IDENTICAL))
+ (void)SvPOK_only_UTF8(sv);
DEBUG_t( Perl_deb(aTHX_ "2.TBL\n"));
@@ -694,6 +695,7 @@ Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg)
SvTAINTED_on(sv);
}
+/* XXX SvUTF8 support missing! */
UV
Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
{
@@ -826,6 +828,7 @@ Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
return retnum;
}
+/* XXX SvUTF8 support missing! */
void
Perl_do_vecset(pTHX_ SV *sv)
{
@@ -841,6 +844,7 @@ Perl_do_vecset(pTHX_ SV *sv)
if (!targ)
return;
s = (unsigned char*)SvPV_force(targ, targlen);
+ (void)SvPOK_only(targ);
lval = SvUV(sv);
offset = LvTARGOFF(sv);
size = LvTARGLEN(sv);
diff --git a/embed.pl b/embed.pl
index 4b27a4bc1c..43dbde5924 100755
--- a/embed.pl
+++ b/embed.pl
@@ -1511,7 +1511,7 @@ Ap |char* |vform |const char* pat|va_list* args
Ap |void |free_tmps
p |OP* |gen_constant_list|OP* o
#if !defined(HAS_GETENV_LEN)
-p |char* |getenv_len |char* key|unsigned long *len
+p |char* |getenv_len |const char* key|unsigned long *len
#endif
Ap |void |gp_free |GV* gv
Ap |GP* |gp_ref |GP* gp
diff --git a/ext/Devel/Peek/Peek.pm b/ext/Devel/Peek/Peek.pm
index 1ef29b476f..101adcd00f 100644
--- a/ext/Devel/Peek/Peek.pm
+++ b/ext/Devel/Peek/Peek.pm
@@ -62,7 +62,7 @@ function. For more information on the format of output of mstat() see
L<perldebug/Using C<$ENV{PERL_DEBUG_MSTATS}>>.
Function C<DumpArray()> allows dumping of multiple values (useful when you
-need to analize returns of functions).
+need to analyze returns of functions).
The global variable $Devel::Peek::pv_limit can be set to limit the
number of character printed in various string values. Setting it to 0
diff --git a/handy.h b/handy.h
index 81f47450d9..de0fa57edd 100644
--- a/handy.h
+++ b/handy.h
@@ -261,7 +261,7 @@ C<strncmp>).
/*
=for apidoc Am|bool|isALNUM|char ch
Returns a boolean indicating whether the C C<char> is an ASCII alphanumeric
-character or digit.
+character (including underscore) or digit.
=for apidoc Am|bool|isALPHA|char ch
Returns a boolean indicating whether the C C<char> is an ASCII alphabetic
diff --git a/lib/Pod/LaTeX.pm b/lib/Pod/LaTeX.pm
new file mode 100644
index 0000000000..8adb58921c
--- /dev/null
+++ b/lib/Pod/LaTeX.pm
@@ -0,0 +1,1567 @@
+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.52';
+
+# 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
+
+ "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 array 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+$//;
+
+ $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 ($paragraph 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') {
+
+ $self->_output("\\item[$paragraph] \\mbox{}");
+ } else {
+ $self->_output('\item ');
+ }
+
+ # 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;
+
+ # 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.4 2000/05/16 01:26:55 timj Exp $
+
+=end __PRIVATE__
+
+=cut
diff --git a/lib/SelfLoader.pm b/lib/SelfLoader.pm
index 99372f2630..3b9c52d912 100644
--- a/lib/SelfLoader.pm
+++ b/lib/SelfLoader.pm
@@ -3,7 +3,7 @@ package SelfLoader;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(AUTOLOAD);
-$VERSION = "1.0901";
+$VERSION = "1.0902";
sub Version {$VERSION}
$DEBUG = 0;
@@ -20,6 +20,7 @@ sub croak { require Carp; goto &Carp::croak }
AUTOLOAD {
print STDERR "SelfLoader::AUTOLOAD for $AUTOLOAD\n" if $DEBUG;
my $SL_code = $Cache{$AUTOLOAD};
+ my $save = $@; # evals in both AUTOLOAD and _load_stubs can corrupt $@
unless ($SL_code) {
# Maybe this pack had stubs before __DATA__, and never initialized.
# Or, this maybe an automatic DESTROY method call when none exists.
@@ -31,11 +32,13 @@ AUTOLOAD {
croak "Undefined subroutine $AUTOLOAD" unless $SL_code;
}
print STDERR "SelfLoader::AUTOLOAD eval: $SL_code\n" if $DEBUG;
+
eval $SL_code;
if ($@) {
$@ =~ s/ at .*\n//;
croak $@;
}
+ $@ = $save;
defined(&$AUTOLOAD) || die "SelfLoader inconsistency error";
delete $Cache{$AUTOLOAD};
goto &$AUTOLOAD
diff --git a/perl.c b/perl.c
index 1cc1a87d04..5df462db9d 100644
--- a/perl.c
+++ b/perl.c
@@ -1609,7 +1609,6 @@ L<perlcall>.
I32
Perl_call_sv(pTHX_ SV *sv, I32 flags)
-
/* See G_* flags in cop.h */
{
dSP;
@@ -1667,7 +1666,7 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
CATCH_SET(oldcatch);
}
else {
- cLOGOP->op_other = PL_op;
+ myop.op_other = (OP*)&myop;
PL_markstack_ptr--;
/* we're trying to emulate pp_entertry() here */
{
diff --git a/pod/perlapi.pod b/pod/perlapi.pod
index cd467ba8ed..2532620d7c 100644
--- a/pod/perlapi.pod
+++ b/pod/perlapi.pod
@@ -670,7 +670,7 @@ Undefines the hash.
=item isALNUM
Returns a boolean indicating whether the C C<char> is an ASCII alphanumeric
-character or digit.
+character (including underscore) or digit.
bool isALNUM(char ch)
diff --git a/pod/perldata.pod b/pod/perldata.pod
index ac444fa17c..a2bb840b01 100644
--- a/pod/perldata.pod
+++ b/pod/perldata.pod
@@ -303,7 +303,8 @@ price is $Z<>100."
print "The price is $Price.\n"; # interpreted
As in some shells, you can enclose the variable name in braces to
-disambiguate it from following alphanumerics. You must also do
+disambiguate it from following alphanumerics (and underscores).
+You must also do
this when interpolating a variable into a string to separate the
variable name from a following double-colon or an apostrophe, since
these would be otherwise treated as a package separator:
diff --git a/pod/perlfaq6.pod b/pod/perlfaq6.pod
index bf007ee26b..29136abd96 100644
--- a/pod/perlfaq6.pod
+++ b/pod/perlfaq6.pod
@@ -415,7 +415,8 @@ Use the split function:
Note that this isn't really a word in the English sense; it's just
chunks of consecutive non-whitespace characters.
-To work with only alphanumeric sequences, you might consider
+To work with only alphanumeric sequences (including underscores), you
+might consider
while (<>) {
foreach $word (m/(\w+)/g) {
diff --git a/pod/perlfaq9.pod b/pod/perlfaq9.pod
index 16a803c997..d1bd593dfe 100644
--- a/pod/perlfaq9.pod
+++ b/pod/perlfaq9.pod
@@ -215,7 +215,8 @@ Here's an example of decoding:
$string =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/ge;
Encoding is a bit harder, because you can't just blindly change
-all the non-alphanumunder character (C<\W>) into their hex escapes.
+all characters that are not letters, digits or underscores (C<\W>)
+into their hex escapes.
It's important that characters with special meaning like C</> and C<?>
I<not> be translated. Probably the easiest way to get this right is
to avoid reinventing the wheel and just use the URI::Escape module,
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index f24c1d2ad3..ce08134532 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -4304,11 +4304,9 @@ Example, assuming array lengths are passed before arrays:
Splits a string into a list of strings and returns that list. By default,
empty leading fields are preserved, and empty trailing ones are deleted.
-If not in list context, returns the number of fields found and splits into
-the C<@_> array. (In list context, you can force the split into C<@_> by
-using C<??> as the pattern delimiters, but it still returns the list
-value.) The use of implicit split to C<@_> is deprecated, however, because
-it clobbers your subroutine arguments.
+In scalar context, returns the number of fields found and splits into
+the C<@_> array. Use of split in scalar context is deprecated, however,
+because it clobbers your subroutine arguments.
If EXPR is omitted, splits the C<$_> string. If PATTERN is also omitted,
splits on whitespace (after skipping any leading whitespace). Anything
diff --git a/pod/perllocale.pod b/pod/perllocale.pod
index 55ccf441fd..ddb5a6e710 100644
--- a/pod/perllocale.pod
+++ b/pod/perllocale.pod
@@ -449,7 +449,7 @@ if you "use locale".
a A b B c C d D e E
a b c d e A B C D E
-Here is a code snippet to tell what alphanumeric
+Here is a code snippet to tell what "word"
characters are in the current locale, in that locale's order:
use locale;
@@ -518,8 +518,9 @@ results, and so always obey the current C<LC_COLLATE> locale.
In the scope of S<C<use locale>>, Perl obeys the C<LC_CTYPE> locale
setting. This controls the application's notion of which characters are
alphabetic. This affects Perl's C<\w> regular expression metanotation,
-which stands for alphanumeric characters--that is, alphabetic and
-numeric characters. (Consult L<perlre> for more information about
+which stands for alphanumeric characters--that is, alphabetic,
+numeric, and including other special characters such as the underscore or
+hyphen. (Consult L<perlre> for more information about
regular expressions.) Thanks to C<LC_CTYPE>, depending on your locale
setting, characters like 'E<aelig>', 'E<eth>', 'E<szlig>', and
'E<oslash>' may be understood as C<\w> characters.
diff --git a/pod/perlre.pod b/pod/perlre.pod
index a82ab32b73..15e58c1cf9 100644
--- a/pod/perlre.pod
+++ b/pod/perlre.pod
@@ -254,15 +254,15 @@ backspace are control characters. All characters with ord() less than
=item graph
-Any alphanumeric or punctuation character.
+Any alphanumeric or punctuation (special) character.
=item print
-Any alphanumeric or punctuation character or space.
+Any alphanumeric or punctuation (special) character or space.
=item punct
-Any punctuation character.
+Any punctuation (special) character.
=item xdigit
@@ -381,6 +381,7 @@ use for a pattern. Simply quote all non-"word" characters:
$pattern =~ s/(\W)/\\$1/g;
+(If C<use locale> is set, then this depends on the current locale.)
Today it is more common to use the quotemeta() function or the C<\Q>
metaquoting escape sequence to disable all metacharacters' special
meanings like this:
diff --git a/pod/perltrap.pod b/pod/perltrap.pod
index 3f54edef2b..c59ecc4daf 100644
--- a/pod/perltrap.pod
+++ b/pod/perltrap.pod
@@ -586,6 +586,12 @@ Some error messages will be different.
=item * Discontinuance
+In Perl 4, if in list context the delimiters to the first argument of
+C<split()> were C<??>, the result would be placed in C<@_> as well as
+being returned. Perl 5 has more respect for your subroutine arguments.
+
+=item * Discontinuance
+
Some bugs may have been inadvertently removed. :-)
=back
diff --git a/pod/pod2latex.PL b/pod/pod2latex.PL
index 71115f3f21..3d3cfb65bc 100644
--- a/pod/pod2latex.PL
+++ b/pod/pod2latex.PL
@@ -34,676 +34,314 @@ $Config{startperl}
# In the following, perl variables are not expanded during extraction.
print OUT <<'!NO!SUBS!';
-#
-# pod2latex, version 1.1
-# by Taro Kawagish (kawagish@imslab.co.jp), Jan 11, 1995.
-#
-# pod2latex filters Perl pod documents to LaTeX documents.
-#
-# What pod2latex does:
-# 1. Pod file 'perl_doc_entry.pod' is filtered to 'perl_doc_entry.tex'.
-# 2. Indented paragraphs are translated into
-# '\begin{verbatim} ... \end{verbatim}'.
-# 3. '=head1 heading' command is translated into '\section{heading}'
-# 4. '=head2 heading' command is translated into '\subsection*{heading}'
-# 5. '=over N' command is translated into
-# '\begin{itemize}' if following =item starts with *,
-# '\begin{enumerate}' if following =item starts with 1.,
-# '\begin{description}' if else.
-# (indentation level N is ignored.)
-# 6. '=item * heading' command is translated into '\item heading',
-# '=item 1. heading' command is translated into '\item heading',
-# '=item heading' command(other) is translated into '\item[heading]'.
-# 7. '=back' command is translated into
-# '\end{itemize}' if started with '\begin{itemize}',
-# '\end{enumerate}' if started with '\begin{enumerate}',
-# '\end{description}' if started with '\begin{description}'.
-# 8. other paragraphs are translated into strings with TeX special characters
-# escaped.
-# 9. In heading text, and other paragraphs, the following translation of pod
-# quotes are done, and then TeX special characters are escaped after that.
-# I<text> to {\em text\/},
-# B<text> to {\bf text},
-# S<text> to text1,
-# where text1 is a string with blank characters replaced with ~,
-# C<text> to {\tt text2},
-# where text2 is a string with TeX special characters escaped to
-# obtain a literal printout,
-# E<text> (HTML escape) to TeX escaped string,
-# L<text> to referencing string as is done by pod2man,
-# F<file> to {\em file\/},
-# Z<> to a null string,
-# 10. those headings are indexed:
-# '=head1 heading' => \section{heading}\index{heading}
-# '=head2 heading' => \subsection*{heading}\index{heading}
-# only when heading does not match frequent patterns such as
-# DESCRIPTION, DIAGNOSTICS,...
-# '=item heading' => \item{heading}\index{heading}
-#
-# Usage:
-# pod2latex perl_doc_entry.pod
-# this will write to a file 'perl_doc_entry.tex'.
-#
-# To LaTeX:
-# The following commands need to be defined in the preamble of the LaTeX
-# document:
-# \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}}
-# \def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}}
-# and \parindent should be set zero:
-# \setlength{\parindent}{0pt}
-#
-# Note:
-# This script was written modifing pod2man.
-#
-# Bug:
-# If HTML escapes E<text> other than E<amp>,E<lt>,E<gt>,E<quot> are used
-# in C<>, translation will produce wrong character strings.
-# Translation of HTML escapes of various European accents might be wrong.
-
-
-# TeX special characters.
-##$tt_ables = "!@*()-=+|;:'\"`,./?<>";
-$backslash_escapables = "#\$%&{}_";
-$backslash_escapables2 = "#\$%&{}"; # except _
-##$nonverbables = "^\\~";
-##$bracketesc = "[]";
-##@tex_verb_fences = unpack("aaaaaaaaa","|#@!*+?:;");
-
-@head1_freq_patterns # =head1 patterns which need not be index'ed
- = ("AUTHOR","Author","BUGS","DATE","DESCRIPTION","DIAGNOSTICS",
- "ENVIRONMENT","EXAMPLES","FILES","INTRODUCTION","NAME","NOTE",
- "SEE ALSO","SYNOPSIS","WARNING");
-
-$indent = 0;
-
-# parse the pods, produce LaTeX.
-
-use Pod::Plainer;
-open(POD,"-|") or Pod::Plainer -> new() -> parse_from_file($ARGV[0]), exit;
-
-($pod=$ARGV[0]) =~ s/\.pod$//;
-open(LATEX,">$pod.tex");
-&do_hdr();
-
-$cutting = 1;
-$begun = "";
-$/ = ""; # record separator is blank lines
-while (<POD>) {
- if ($cutting) {
- next unless /^=/;
- $cutting = 0;
- }
- if ($begun) {
- if (/^=end\s+$begun/) {
- $begun = "";
- }
- elsif ($begun =~ /^(tex|latex)$/) {
- print LATEX $_;
- }
- next;
- }
- chop;
- length || (print LATEX "\n") && next;
-
- # translate indented lines as a verabatim paragraph
- if (/^\s/) {
- @lines = split(/\n/);
- print LATEX "\\begin{verbatim}\n";
- for (@lines) {
- 1 while s
- {^( [^\t]* ) \t ( \t* ) }
- { $1 . ' ' x (8 - (length($1)%8) + 8*(length($2))) }ex;
- print LATEX $_,"\n";
- }
- print LATEX "\\end{verbatim}\n";
- next;
- }
- if (/^=for\s+(\S+)\s*/s) {
- if ($1 eq "tex" or $1 eq "latex") {
- print LATEX $',"\n";
- } else {
- # ignore unknown for
- }
- next;
- }
- elsif (/^=begin\s+(\S+)\s*/s) {
- $begun = $1;
- if ($1 eq "tex" or $1 eq "latex") {
- print LATEX $'."\n";
- }
- next;
- }
+# pod2latex conversion program
+
+use Pod::LaTeX;
+use Pod::Find qw/ pod_find /;
+use Pod::Usage;
+use Getopt::Long;
+use File::Basename;
+
+# Read command line arguments
+
+my %options = (
+ "help" => 0,
+ "man" => 0,
+ "sections" => [],
+ "full" => 0,
+ "out" => undef,
+ "verbose" => 0,
+ "modify" => 0,
+ );
+
+GetOptions(\%options,
+ "help",
+ "man",
+ "verbose",
+ "full",
+ "sections=s@",
+ "out=s",
+ "modify",
+ ) || pod2usage(2);
+
+pod2usage(1) if ($options{help});
+pod2usage(-verbose => 2) if ($options{man});
+
+
+# Read all the files from the command line
+my @files = @ARGV;
+
+# Now find which ones are real pods and convert
+# directories to their contents.
+
+# Extract the pods from each arg since some of them might
+# be directories
+# This is not as efficient as using pod_find to search through
+# everything at once but it allows us to preserve the order
+# supplied by the user
+
+my @pods;
+foreach my $arg (@files) {
+ my %pods = pod_find($arg);
+ push(@pods, sort keys %pods);
+}
- # preserve '=item' line with pod quotes as they are.
- if (/^=item/) {
- ($bareitem = $_) =~ s/^=item\s*//;
- }
+# Abort if nothing to do
+if ($#pods == -1) {
+ warn "None of the supplied Pod files actually exist\n";
+ exit;
+}
- # check for things that'll hosed our noremap scheme; affects $_
- &init_noremap();
-
- # expand strings "func()" as pod quotes.
- if (!/^=item/) {
- # first hide pod escapes.
- # escaped strings are mapped into the ones with the MSB's on.
- s/([A-Z]<[^<>]*>)/noremap($1)/ge;
-
- # func() is a reference to a perl function
- s{\b([:\w]+\(\))}{I<$1>}g;
- # func(n) is a reference to a man page
- s{(\w+)(\([^\s,\051]+\))}{I<$1>$2}g;
- # convert simple variable references
-# s/([\$\@%][\w:]+)/C<$1>/g;
-# s/\$[\w:]+\[[0-9]+\]/C<$&>/g;
-
- if (m{ ([\-\w]+\([^\051]*?[\@\$,][^\051]*?\))
- }x && $` !~ /([LCI]<[^<>]*|-)$/ && !/^=\w/)
- {
- warn "``$1'' should be a [LCI]<$1> ref";
- }
- while (/(-[a-zA-Z])\b/g && $` !~ /[\w\-]$/) {
- warn "``$1'' should be [CB]<$1> ref";
- }
-
- # put back pod quotes so we get the inside of <> processed;
- $_ = &clear_noremap($_);
- }
- # process TeX special characters
-
- # First hide HTML quotes E<> since they can be included in C<>.
- s/(E<[^<>]+>)/noremap($1)/ge;
-
- # Then hide C<> type literal quotes.
- # String inside of C<> will later be expanded into {\tt ..} strings
- # with TeX special characters escaped as needed.
- s/(C<[^<>]*>)/&noremap($1)/ge;
-
- # Next escape TeX special characters including other pod quotes B< >,...
- #
- # NOTE: s/re/&func($str)/e evaluates $str just once in perl5.
- # (in perl4 evaluation takes place twice before getting passed to func().)
-
- # - hyphen => ---
- s/(\S+)(\s+)-+(\s+)(\S+)/"$1".&noremap(" --- ")."$4"/ge;
- # '-', '--', "-" => '{\tt -}', '{\tt --}', "{\tt -}"
-## s/("|')(\s*)(-+)(\s*)\1/&noremap("$1$2\{\\tt $3\}$4$1")/ge;
-## changed Wed Jan 25 15:26:39 JST 1995
- # '-', '--', "-" => '$-$', '$--$', "$-$"
- s/(\s+)(['"])(-+)([^'"\-]*)\2(\s+|[,.])/"$1$2".&noremap("\$$3\$")."$4$2$5"/ge;
- s/(\s+)(['"])([^'"\-]*)(-+)(\s*)\2(\s+|[,.])/"$1$2$3".&noremap("\$$4\$")."$5$2$6"/ge;
- # (--|-) => ($--$|$-$)
- s/(\s+)\((-+)([=@%\$\+\\\|\w]*)(-*)([=@%\$\+\\\|\w]*)\)(\s+|[,.])/"$1\(".&noremap("\$$2\$")."$3".&noremap("\$$4\$")."$5\)$6"/ge;
- # numeral - => $-$
- s/(\(|[0-9]+|\s+)-(\s*\(?\s*[0-9]+)/&noremap("$1\$-\$$2")/ge;
- # -- in quotes => two separate -
- s/B<([^<>]*)--([^<>]*)>/&noremap("B<$1\{\\tt --\}$2>")/ge;
-
- # backslash escapable characters except _.
- s/([$backslash_escapables2])/&noremap("\\$1")/ge;
- s/_/&noremap("\\underscore{}")/ge; # a litle thicker than \_.
- # quote TeX special characters |, ^, ~, \.
- s/\|/&noremap("\$|\$")/ge;
- s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge;
- s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge;
- s/\\/&noremap("\$\\backslash{}\$")/ge;
- # quote [ and ] to be used in \item[]
- s/([\[\]])/&noremap("{\\tt $1}")/ge;
- # characters need to be treated differently in TeX
- # keep * if an item heading
- s/^(=item[ \t]+)[*]((.|\n)*)/"$1" . &noremap("*") . "$2"/ge;
- s/[*]/&noremap("\$\\ast\$")/ge; # other *
-
- # hide other pod quotes.
- s/([ABD-Z]<[^<>]*>)/&noremap($1)/ge;
-
- # escape < and > as math strings,
- # now that we are done with hiding pod <> quotes.
- s/</&noremap("\$<\$")/ge;
- s/>/&noremap("\$>\$")/ge;
-
- # put it back so we get the <> processed again;
- $_ = &clear_noremap($_);
-
-
- # Expand pod quotes recursively:
- # (1) type face directives [BIFS]<[^<>]*> to appropriate TeX commands,
- # (2) L<[^<>]*> to reference strings,
- # (3) C<[^<>]*> to TeX literal quotes,
- # (4) HTML quotes E<> inside of C<> quotes.
-
- # Hide E<> again since they can be included in C<>.
- s/(E<[^<>]+>)/noremap($1)/ge;
-
- $maxnest = 10;
- while ($maxnest-- && /[A-Z]</) {
-
- # bold and italic quotes
- s/B<([^<>]*)>/"{\\bf $1}"/eg;
- s#I<([^<>]*)>#"{\\em $1\\/}"#eg;
-
- # files and filelike refs in italics
- s#F<([^<>]*)>#"{\\em $1\\/}"#eg;
-
- # no break quote -- usually we want C<> for this
- s/S<([^<>]*)>/&nobreak($1)/eg;
-
- # LREF: a manpage(3f)
- s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))?>:the {\\em $1\\/}$2 manpage:g;
-
- # LREF: an =item on another manpage
- s{
- L<([^/]+)/([:\w]+(\(\))?)>
- } {the C<$2> entry in the I<$1> manpage}gx;
-
- # LREF: an =item on this manpage
- s{
- ((?:L</([:\w]+(\(\))?)>
- (,?\s+(and\s+)?)?)+)
- } { &internal_lrefs($1) }gex;
-
- # LREF: a =head2 (head1?), maybe on a manpage, maybe right here
- # the "func" can disambiguate
- s{
- L<(?:([a-zA-Z]\S+?) /)?"?(.*?)"?>
- }{
- do {
- $1 # if no $1, assume it means on this page.
- ? "the section on I<$2> in the I<$1> manpage"
- : "the section on I<$2>"
- }
- }gex;
-
- s/X<([^<>]*)>/\\index{$1}/g;
-
- s/Z<>/\\&/g; # the "don't format me" thing
-
- # comes last because not subject to reprocessing
- s{
- C<([^<>]*)>
- }{
- do {
- ($str = $1) =~ tr/\200-\377/\000-\177/; #normalize hidden stuff
- # expand HTML escapes if any;
- # WARNING: if HTML escapes other than E<amp>,E<lt>,E<gt>,
- # E<quot> are in C<>, they will not be printed correctly.
- $str = &expand_HTML_escapes($str);
- $strverb = &alltt($str); # Tex verbatim escape of a string.
- &noremap("$strverb");
- }
- }gex;
-
-# if ( /C<([^<>]*)/ ) {
-# $str = $1;
-# if ($str !~ /\|/) { # if includes |
-# s/C<([^<>]*)>/&noremap("\\verb|$str|")/eg;
-# } else {
-# print STDERR "found \| in C<.*> at paragraph $.\n";
-# # find a character not contained in $str to use it as a
-# # separator of the \verb
-# ($chars = $str) =~ s/(\W)/\\$1/g;
-# ## ($chars = $str) =~ s/([\$<>,\|"'\-^{}()*+?\\])/\\$1/g;
-# @fence = grep(!/[ $chars]/,@tex_verb_fences);
-# s/C<([^<>]*)>/&noremap("\\verb$fence[0]$str$fence[0]")/eg;
-# }
-# }
- }
+# If $options{'out'} is set we are processing to a single output file
+my $multi_documents;
+if (exists $options{'out'} && defined $options{'out'}) {
+ $multi_documents = 0;
+} else {
+ $multi_documents = 1;
+}
+
+# If the output file is not specified it is assumed that
+# a single output file is required per input file using
+# a .tex extension rather than any exisiting extension
+
+if ($multi_documents) {
+
+ # Case where we just generate one input per output
+
+ foreach my $pod (@pods) {
+
+ if (-f $pod) {
+
+ my $output = $pod;
+ $output = basename($output, '.pm', '.pod','.pl') . '.tex';
+ # Create a new parser object
+ my $parser = new Pod::LaTeX(
+ AddPreamble => $options{'full'},
+ AddPostamble => $options{'full'},
+ MakeIndex => $options{'full'},
+ TableOfContents => $options{'full'},
+ ReplaceNAMEwithSection => $options{'modify'},
+ UniqueLabels => $options{'modify'},
+ );
- # process each pod command
- if (s/^=//) { # if a command
- s/\n/ /g;
- ($cmd, $rest) = split(' ', $_, 2);
- $rest =~ s/^\s*//;
- $rest =~ s/\s*$//;
-
- if (defined $rest) {
- &escapes;
- }
-
- $rest = &clear_noremap($rest);
- $rest = &expand_HTML_escapes($rest);
-
- if ($cmd eq 'cut') {
- $cutting = 1;
- $lastcmd = 'cut';
- }
- elsif ($cmd eq 'head1') { # heading type 1
- $rest =~ s/^\s*//; $rest =~ s/\s*$//;
- print LATEX "\n\\subsection*{$rest}";
- # put index entry
- ($index = $rest) =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The'
- # index only those heads not matching the frequent patterns.
- foreach $pat (@head1_freq_patterns) {
- if ($index =~ /^$pat/) {
- goto freqpatt;
- }
- }
- print LATEX "%\n\\index{$index}\n" if ($index);
- freqpatt:
- $lastcmd = 'head1';
- }
- elsif ($cmd eq 'head2') { # heading type 2
- $rest =~ s/^\s*//; $rest =~ s/\s*$//;
- print LATEX "\n\\subsubsection*{$rest}";
- # put index entry
- ($index = $rest) =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The'
- $index =~ s/^Example\s*[1-9][0-9]*\s*:\s*//; # remove 'Example :'
- print LATEX "%\n\\index{$index}\n" if ($index);
- $lastcmd = 'head2';
- }
- elsif ($cmd eq 'over') { # 1 level within a listing environment
- push(@indent,$indent);
- $indent = $rest + 0;
- $lastcmd = 'over';
- }
- elsif ($cmd eq 'back') { # 1 level out of a listing environment
- $indent = pop(@indent);
- warn "Unmatched =back\n" unless defined $indent;
- $listingcmd = pop(@listingcmd);
- print LATEX "\n\\end{$listingcmd}\n" if ($listingcmd);
- $lastcmd = 'back';
- }
- elsif ($cmd eq 'item') { # an item paragraph starts
- if ($lastcmd eq 'over') { # if we have just entered listing env
- # see what type of list environment we are in.
- if ($rest =~ /^[0-9]\.?/) { # if numeral heading
- $listingcmd = 'enumerate';
- } elsif ($rest =~ /^\*\s*/) { # if * heading
- $listingcmd = 'itemize';
- } elsif ($rest =~ /^[^*]/) { # if other headings
- $listingcmd = 'description';
- } else {
- warn "unknown list type for item $rest";
- }
- print LATEX "\n\\begin{$listingcmd}\n";
- push(@listingcmd,$listingcmd);
- } elsif ( !@listingcmd ) {
- warn "Illegal '=item' command without preceding 'over':";
- warn "=item $bareitem";
- }
-
- if ($listingcmd eq 'enumerate') {
- $rest =~ s/^[0-9]+\.?\s*//; # remove numeral heading
- print LATEX "\n\\item";
- print LATEX "{\\bf $rest}" if $rest;
- } elsif ($listingcmd eq 'itemize') {
- $rest =~ s/^\*\s*//; # remove * heading
- print LATEX "\n\\item";
- print LATEX "{\\bf $rest}" if $rest;
- } else { # description item
- print LATEX "\n\\item[$rest]";
- }
- $lastcmd = 'item';
- $rightafter_item = 'yes';
-
- # check if the item heading is short or long.
- ($itemhead = $rest) =~ s/{\\bf (\S*)}/$1/g;
- if (length($itemhead) < 4) {
- $itemshort = "yes";
- } else {
- $itemshort = "no";
- }
- # write index entry
- if ($pod =~ "perldiag") { # skip 'perldiag.pod'
- goto noindex;
- }
- # strip out the item of pod quotes and get a plain text entry
- $bareitem =~ s/\n/ /g; # remove newlines
- $bareitem =~ s/\s*$//; # remove trailing space
- $bareitem =~ s/[A-Z]<([^<>]*)>/$1/g; # remove <> quotes
- ($index = $bareitem) =~ s/^\*\s+//; # remove leading '*'
- $index =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The'
- $index =~ s/^\s*[1-9][0-9]*\s*[.]\s*$//; # remove numeral only
- $index =~ s/^\s*\w\s*$//; # remove 1 char only's
- # quote ", @ and ! with " to be used in makeindex.
- $index =~ s/"/""/g; # quote "
- $index =~ s/@/"@/g; # quote @
- $index =~ s/!/"!/g; # quote !
- ($rest2=$rest) =~ s/^\*\s+//; # remove *
- $rest2 =~ s/"/""/g; # quote "
- $rest2 =~ s/@/"@/g; # quote @
- $rest2 =~ s/!/"!/g; # quote !
- if ($pod =~ "(perlfunc|perlvar)") { # when doc is perlfunc,perlvar
- # take only the 1st word of item heading
- $index =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/;
- $rest2 =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/;
- }
- if ($index =~ /[A-Za-z\$@%]/) {
- # write \index{plain_text_entry@TeX_string_entry}
- print LATEX "%\n\\index{$index\@$rest2}%\n";
- }
- noindex:
- ;
- }
- elsif ($cmd eq 'pod') {
- ; # recognise the pod directive, as no op (hs)
- }
- elsif ($cmd eq 'pod') {
- ; # recognise the pod directive, as no op (hs)
- }
- else {
- warn "Unrecognized directive: $cmd\n";
- }
+ # Select sections if supplied
+ $parser->select(@{ $options{'sections'}})
+ if @{$options{'sections'}};
+
+ # Derive the input file from the output file
+ $parser->parse_from_file($pod, $output);
+
+ print "Written output to $output\n" if $options{'verbose'};
+
+ } else {
+ warn "File $pod not found\n";
}
- else { # if not command
- &escapes;
- $_ = &clear_noremap($_);
- $_ = &expand_HTML_escapes($_);
-
- # if the present paragraphs follows an =item declaration,
- # put a line break.
- if ($lastcmd eq 'item' &&
- $rightafter_item eq 'yes' && $itemshort eq "no") {
- print LATEX "\\hfil\\\\";
- $rightafter_item = 'no';
- }
- print LATEX "\n",$_;
+
+ }
+} else {
+
+ # Case where we want everything to be in a single document
+
+ # Need to open the output file ourselves
+ my $output = $options{'out'};
+ $output .= '.tex' unless $output =~ /\.tex$/;
+
+ # Use auto-vivified file handle in perl 5.6
+ use Symbol;
+ my $outfh = gensym;
+ open ($outfh, ">$output") || die "Could not open output file: $!\n";
+
+ # Flag to indicate whether we have converted at least one file
+ # indicates how many files have been converted
+ my $converted = 0;
+
+ # Loop over the input files
+ foreach my $pod (@pods) {
+
+ if (-f $pod) {
+
+ warn "Converting $pod\n" if $options{'verbose'};
+
+ # Open the file (need the handle)
+ # Use auto-vivified handle in perl 5.6
+ my $podfh = gensym;
+ open ($podfh, "<$pod") || die "Could not open pod file $pod: $!\n";
+
+ # if this is the first file to be converted we may want to add
+ # a preamble (controlled by command line option)
+ if ($converted == 0 && $options{'full'}) {
+ $preamble = 1;
+ } else {
+ $preamble = 0;
+ }
+
+ # if this is the last file to be converted may want to add
+ # a postamble (controlled by command line option)
+ # relies on a previous pass to check existence of all pods we
+ # are converting.
+ my $postamble = ( ($converted == $#pods && $options{'full'}) ? 1 : 0 );
+
+ # Open parser object
+ # May want to start with a preamble for the first one and
+ # end with an index for the last
+ my $parser = new Pod::LaTeX(
+ MakeIndex => $options{'full'},
+ TableOfContents => $preamble,
+ ReplaceNAMEwithSection => $options{'modify'},
+ UniqueLabels => $options{'modify'},
+ StartWithNewPage => $options{'full'},
+ AddPreamble => $preamble,
+ AddPostamble => $postamble,
+ );
+
+ # Store the file name for error messages
+ # This is a kluge that breaks the data hiding of the object
+ $parser->{_INFILE} = $pod;
+
+ # Select sections if supplied
+ $parser->select(@{ $options{'sections'}})
+ if @{$options{'sections'}};
+
+ # Parse it
+ $parser->parse_from_filehandle($podfh, $outfh);
+
+ # We have converted at least one file
+ $converted++;
+
+ } else {
+ warn "File $pod not found\n";
}
-}
-print LATEX "\n";
-close(POD);
-close(LATEX);
+ }
+ # Should unlink the file if we didn't convert anything!
+ # dont check for return status of unlink
+ # since there is not a lot to be done if the unlink failed
+ # and the program does not rely upon it.
+ unlink "$output" unless $converted;
-#########################################################################
+ # If verbose
+ warn "Converted $converted files\n" if $options{'verbose'};
-sub do_hdr {
- print LATEX "% LaTeX document produced by pod2latex from \"$pod.pod\".\n";
- print LATEX "% The followings need be defined in the preamble of this document:\n";
- print LATEX "%\\def\\C++{{\\rm C\\kern-.05em\\raise.3ex\\hbox{\\footnotesize ++}}}\n";
- print LATEX "%\\def\\underscore{\\leavevmode\\kern.04em\\vbox{\\hrule width 0.4em height 0.3pt}}\n";
- print LATEX "%\\setlength{\\parindent}{0pt}\n";
- print LATEX "\n";
- $podq = &escape_tex_specials("\U$pod\E");
- print LATEX "\\section{$podq}%\n";
- print LATEX "\\index{$podq}";
- print LATEX "\n";
}
-sub nobreak {
- my $string = shift;
- $string =~ s/ +/~/g; # TeX no line break
- $string;
-}
+exit;
-sub noremap {
- local($thing_to_hide) = shift;
- $thing_to_hide =~ tr/\000-\177/\200-\377/;
- return $thing_to_hide;
-}
+__END__
-sub init_noremap {
- # escape high bit characters in input stream
- s/([\200-\377])/"E<".ord($1).">"/ge;
-}
+=head1 NAME
-sub clear_noremap {
- local($tmp) = shift;
- $tmp =~ tr/\200-\377/\000-\177/;
- return $tmp;
-}
+pod2latex - convert pod documentation to latex format
-sub expand_HTML_escapes {
- local($s) = $_[0];
- $s =~ s { E<((\d+)|([A-Za-z]+))> }
- {
- do {
- defined($2)
- ? do { chr($2) }
- :
- exists $HTML_Escapes{$3}
- ? do { $HTML_Escapes{$3} }
- : do {
- warn "Unknown escape: $& in $_";
- "E<$1>";
- }
- }
- }egx;
- return $s;
-}
+=head1 SYNOPSIS
-sub escapes {
- # make C++ into \C++, which is to be defined as
- # \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}}
- s/\bC\+\+/\\C++{}/g;
-}
+ pod2latex *.pm
-# Translate a string into a TeX \tt string to obtain a verbatim print out.
-# TeX special characters are escaped by \.
-# This can be used inside of LaTeX command arguments.
-# We don't use LaTeX \verb since it doesn't work inside of command arguments.
-sub alltt {
- local($str) = shift;
- # other chars than #,\,$,%,&,{,},_,\,^,~ ([ and ] included).
- $str =~ s/([^${backslash_escapables}\\\^\~]+)/&noremap("$&")/eg;
- # chars #,\,$,%,&,{,} => \# , ...
- $str =~ s/([$backslash_escapables2])/&noremap("\\$&")/eg;
- # chars _,\,^,~ => \char`\_ , ...
- $str =~ s/_/&noremap("\\char`\\_")/eg;
- $str =~ s/\\/&noremap("\\char`\\\\")/ge;
- $str =~ s/\^/\\char`\\^/g;
- $str =~ s/\~/\\char`\\~/g;
-
- $str =~ tr/\200-\377/\000-\177/; # put back
- $str = "{\\tt ".$str."}"; # make it a \tt string
- return $str;
-}
+ pod2latex -out mytex.tex *.pod
-sub escape_tex_specials {
- local($str) = shift;
- # other chars than #,\,$,%,&,{,}, _,\,^,~ ([ and ] included).
- # backslash escapable characters #,\,$,%,&,{,} except _.
- $str =~ s/([$backslash_escapables2])/&noremap("\\$1")/ge;
- $str =~ s/_/&noremap("\\underscore{}")/ge; # \_ is too thin.
- # quote TeX special characters |, ^, ~, \.
- $str =~ s/\|/&noremap("\$|\$")/ge;
- $str =~ s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge;
- $str =~ s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge;
- $str =~ s/\\/&noremap("\$\\backslash{}\$")/ge;
- # characters need to be treated differently in TeX
- # *
- $str =~ s/[*]/&noremap("\$\\ast\$")/ge;
- # escape < and > as math string,
- $str =~ s/</&noremap("\$<\$")/ge;
- $str =~ s/>/&noremap("\$>\$")/ge;
- $str =~ tr/\200-\377/\000-\177/; # put back
- return $str;
-}
+ pod2latex -full -sections 'DESCRIPTION|NAME' SomeDir
-sub internal_lrefs {
- local($_) = shift;
-
- s{L</([^>]+)>}{$1}g;
- my(@items) = split( /(?:,?\s+(?:and\s+)?)/ );
- my $retstr = "the ";
- my $i;
- for ($i = 0; $i <= $#items; $i++) {
- $retstr .= "C<$items[$i]>";
- $retstr .= ", " if @items > 2 && $i != $#items;
- $retstr .= " and " if $i+2 == @items;
- }
- $retstr .= " entr" . ( @items > 1 ? "ies" : "y" )
- . " elsewhere in this document";
+=head1 DESCRIPTION
- return $retstr;
-}
+C<pod2latex> is a program to convert POD format documentation
+(L<perlpod>) into latex. It can process multiple input documents at a
+time and either generate a latex file per input document or a single
+combined output file.
+
+=head1 OPTIONS AND ARGUMENTS
+
+This section describes the supported command line options. Minium
+matching is supported.
+
+=over 4
+
+=item B<-out>
+
+Name of the output file to be used. If there are multiple input pods
+it is assumed that the intention is to write all translated output
+into a single file. C<.tex> is appended if not present. If the
+argument is not supplied, a single document will be created for each
+input file.
+
+=item B<-full>
+
+Creates a complete C<latex> file that can be processed immediately
+(unless C<=for/=begin> directives are used that rely on extra packages).
+Table of contents and index generation commands are included in the
+wrapper C<latex> code.
+
+=item B<-sections>
+
+Specify pod sections to include (or remove if negated) in the
+translation. See L<Pod::Select/"SECTION SPECIFICATIONS"> for the
+format to use for I<section-spec>. This option may be given multiple
+times on the command line.This is identical to the similar option in
+the C<podselect()> command.
+
+=item B<-modify>
+
+This option causes the output C<latex> to be slightly
+modified from the input pod such that when a C<=head1 NAME>
+is encountered a section is created containing the actual
+pod name (rather than B<NAME>) and all subsequent C<=head1>
+directives are treated as subsections. This has the advantage
+that the description of a module will be in its own section
+which is helpful for including module descriptions in documentation.
+Also forces C<latex> label and index entries to be prefixed by the
+name of the module.
+
+=item B<-help>
+
+Print a brief help message and exit.
+
+=item B<-man>
+
+Print the manual page and exit.
+
+=item B<-verbose>
+
+Print information messages as each document is processed.
+
+=back
+
+=head1 BUGS
+
+Known bugs are:
+
+=over 4
+
+=item *
+
+Cross references between documents are not resolved when multiple
+pod documents are converted into a single output C<latex> file.
+
+=item *
+
+Functions and variables are not automatically recognized
+and they will therefore not be marked up in any special way
+unless instructed by an explicit pod command.
+
+=back
+
+=head1 SEE ALSO
+
+L<Pod::LaTeX>
+
+=head1 AUTHOR
+
+Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>
+
+This program is free software; you can redistribute it
+and/or modify it under the same terms as Perl itself.
+
+Copyright (C) 2000 Tim Jenness.
+
+=cut
-# map of HTML escapes to TeX escapes.
-BEGIN {
-%HTML_Escapes = (
- 'amp' => '&', # ampersand
- 'lt' => '<', # left chevron, less-than
- 'gt' => '>', # right chevron, greater-than
- 'quot' => '"', # double quote
-
- "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
-);
-}
!NO!SUBS!
close OUT or die "Can't close $file: $!";
diff --git a/t/lib/selfloader.t b/t/lib/selfloader.t
new file mode 100755
index 0000000000..9c585a598d
--- /dev/null
+++ b/t/lib/selfloader.t
@@ -0,0 +1,198 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ $dir = "self-$$";
+ unshift @INC, ("./$dir", "../lib");
+
+ print "1..19\n";
+
+ # First we must set up some selfloader files
+ mkdir $dir, 0755 or die "Can't mkdir $dir: $!";
+
+ open(FOO, ">$dir/Foo.pm") or die;
+ print FOO <<'EOT';
+package Foo;
+use SelfLoader;
+
+sub new { bless {}, shift }
+sub foo;
+sub bar;
+sub bazmarkhianish;
+sub a;
+sub never; # declared but definition should never be read
+1;
+__DATA__
+
+sub foo { shift; shift || "foo" };
+
+sub bar { shift; shift || "bar" }
+
+sub bazmarkhianish { shift; shift || "baz" }
+
+package sheep;
+sub bleat { shift; shift || "baa" }
+
+__END__
+sub never { die "D'oh" }
+EOT
+
+ close(FOO);
+
+ open(BAR, ">$dir/Bar.pm") or die;
+ print BAR <<'EOT';
+package Bar;
+use SelfLoader;
+
+@ISA = 'Baz';
+
+sub new { bless {}, shift }
+sub a;
+
+1;
+__DATA__
+
+sub a { 'a Bar'; }
+sub b { 'b Bar' }
+
+__END__ DATA
+sub never { die "D'oh" }
+EOT
+
+ close(BAR);
+};
+
+
+package Baz;
+
+sub a { 'a Baz' }
+sub b { 'b Baz' }
+sub c { 'c Baz' }
+
+
+package main;
+use Foo;
+use Bar;
+
+$foo = new Foo;
+
+print "not " unless $foo->foo eq 'foo'; # selfloaded first time
+print "ok 1\n";
+
+print "not " unless $foo->foo eq 'foo'; # regular call
+print "ok 2\n";
+
+# Try an undefined method
+eval {
+ $foo->will_fail;
+};
+if ($@ =~ /^Undefined subroutine/) {
+ print "ok 3\n";
+} else {
+ print "not ok 3 $@\n";
+}
+
+# Used to be trouble with this
+eval {
+ my $foo = new Foo;
+ die "oops";
+};
+if ($@ =~ /oops/) {
+ print "ok 4\n";
+} else {
+ print "not ok 4 $@\n";
+}
+
+# Pass regular expression variable to autoloaded function. This used
+# to go wrong in AutoLoader because it used regular expressions to generate
+# autoloaded filename.
+"foo" =~ /(\w+)/;
+print "not " unless $1 eq 'foo';
+print "ok 5\n";
+
+print "not " unless $foo->bar($1) eq 'foo';
+print "ok 6\n";
+
+print "not " unless $foo->bar($1) eq 'foo';
+print "ok 7\n";
+
+print "not " unless $foo->bazmarkhianish($1) eq 'foo';
+print "ok 8\n";
+
+print "not " unless $foo->bazmarkhianish($1) eq 'foo';
+print "ok 9\n";
+
+# Check nested packages inside __DATA__
+print "not " unless sheep::bleat() eq 'baa';
+print "ok 10\n";
+
+# Now check inheritance:
+
+$bar = new Bar;
+
+# Before anything is SelfLoaded there is no declaration of Foo::b so we should
+# get Baz::b
+print "not " unless $bar->b() eq 'b Baz';
+print "ok 11\n";
+
+# There is no Bar::c so we should get Baz::c
+print "not " unless $bar->c() eq 'c Baz';
+print "ok 12\n";
+
+# This selfloads Bar::a because it is stubbed. It also stubs Bar::b as a side
+# effect
+print "not " unless $bar->a() eq 'a Bar';
+print "ok 13\n";
+
+print "not " unless $bar->b() eq 'b Bar';
+print "ok 14\n";
+
+print "not " unless $bar->c() eq 'c Baz';
+print "ok 15\n";
+
+
+
+# Check that __END__ is honoured
+# Try an subroutine that should never be noticed by selfloader
+eval {
+ $foo->never;
+};
+if ($@ =~ /^Undefined subroutine/) {
+ print "ok 16\n";
+} else {
+ print "not ok 16 $@\n";
+}
+
+# Try to read from the data file handle
+my $foodata = <Foo::DATA>;
+if (defined $foodata) {
+ print "not ok 17 # $foodata\n";
+} else {
+ print "ok 17\n";
+}
+
+# Check that __END__ DATA is honoured
+# Try an subroutine that should never be noticed by selfloader
+eval {
+ $bar->never;
+};
+if ($@ =~ /^Undefined subroutine/) {
+ print "ok 18\n";
+} else {
+ print "not ok 18 $@\n";
+}
+
+# Try to read from the data file handle
+my $bardata = <Bar::DATA>;
+if ($bardata ne "sub never { die \"D'oh\" }\n") {
+ print "not ok 19 # $bardata\n";
+} else {
+ print "ok 19\n";
+}
+
+# cleanup
+END {
+return unless $dir && -d $dir;
+unlink "$dir/Foo.pm", "$dir/Bar.pm";
+rmdir "$dir";
+}
diff --git a/t/op/tr.t b/t/op/tr.t
index 4e6667cd7f..e9a1b4c42d 100755
--- a/t/op/tr.t
+++ b/t/op/tr.t
@@ -5,7 +5,7 @@ BEGIN {
unshift @INC, "../lib";
}
-print "1..4\n";
+print "1..8\n";
$_ = "abcdefghijklmnopqrstuvwxyz";
@@ -37,3 +37,27 @@ print "ok 3\n";
print "ok 4\n";
}
#
+
+# make sure that tr cancels IOK and NOK
+($x = 12) =~ tr/1/3/;
+(my $y = 12) =~ tr/1/3/;
+($f = 1.5) =~ tr/1/3/;
+(my $g = 1.5) =~ tr/1/3/;
+print "not " unless $x + $y + $f + $g == 71;
+print "ok 5\n";
+
+# make sure tr is harmless if not updating - see [ID 20000511.005]
+$_ = 'fred';
+/([a-z]{2})/;
+$1 =~ tr/A-Z//;
+s/^(\s*)f/$1F/;
+print "not " if $_ ne 'Fred';
+print "ok 6\n";
+
+# check tr handles UTF8 correctly
+($x = 256.65.258) =~ tr/a/b/;
+print "not " if $x ne 256.65.258 or length $x != 3;
+print "ok 7\n";
+$x =~ tr/A/B/;
+print "not " if $x ne 256.66.258 or length $x != 3;
+print "ok 8\n";
diff --git a/t/op/vec.t b/t/op/vec.t
index bf60fc4a08..b8efb8011d 100755
--- a/t/op/vec.t
+++ b/t/op/vec.t
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: vec.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:36 $
-
-print "1..15\n";
+print "1..18\n";
print vec($foo,0,1) == 0 ? "ok 1\n" : "not ok 1\n";
print length($foo) == 0 ? "ok 2\n" : "not ok 2\n";
@@ -25,3 +23,11 @@ vec($Vec, 0, 32) = 0xbaddacab;
print $Vec eq "\xba\xdd\xac\xab" ? "ok 14\n" : "not ok 14\n";
print vec($Vec, 0, 32) == 3135089835 ? "ok 15\n" : "not ok 15\n";
+# ensure vec() handles numericalness correctly
+$foo = $bar = $baz = 0;
+vec($foo = 0,0,1) = 1;
+vec($bar = 0,1,1) = 1;
+$baz = $foo | $bar;
+print $foo eq "1" && $foo == 1 ? "ok 16\n" : "not ok 16\n";
+print $bar eq "2" && $bar == 2 ? "ok 17\n" : "not ok 17\n";
+print "$foo $bar $baz" eq "1 2 3" ? "ok 18\n" : "not ok 18\n";
diff --git a/utils/h2xs.PL b/utils/h2xs.PL
index ca0e7cbc32..8ebe8b30c5 100644
--- a/utils/h2xs.PL
+++ b/utils/h2xs.PL
@@ -688,7 +688,7 @@ warn "Writing $ext$modpname/$modfname.pm\n";
print PM <<"END";
package $module;
-require 5.005_62;
+use 5.006;
use strict;
use warnings;
END
@@ -905,7 +905,7 @@ my $pod = <<"END" unless $opt_P;
#
#=head1 SEE ALSO
#
-#perl(1).
+#L<perl>.
#
#=cut
END