replace pod2latex with the one in Pod-LaTeX v0.52 from CPAN
authorGurusamy Sarathy <gsar@cpan.org>
Thu, 1 Jun 2000 08:50:07 +0000 (08:50 +0000)
committerGurusamy Sarathy <gsar@cpan.org>
Thu, 1 Jun 2000 08:50:07 +0000 (08:50 +0000)
(from Tim Jenness <t.jenness@jach.hawaii.edu>)

p4raw-id: //depot/perl@6187

AUTHORS
MAINTAIN
MANIFEST
ext/Devel/Peek/Peek.pm
lib/Pod/LaTeX.pm [new file with mode: 0644]
pod/pod2latex.PL

diff --git a/AUTHORS b/AUTHORS
index 912dedd..3032d48 100644 (file)
--- 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
index 60ed01e..6d9c60b 100644 (file)
--- a/MAINTAIN
+++ b/MAINTAIN
@@ -434,10 +434,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     
index 68e6ec4..9dfa665 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -643,6 +643,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
index 1ef29b4..101adcd 100644 (file)
@@ -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/lib/Pod/LaTeX.pm b/lib/Pod/LaTeX.pm
new file mode 100644 (file)
index 0000000..8adb589
--- /dev/null
@@ -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
index 71115f3..3d3cfb6 100644 (file)
@@ -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: $!";