[Darshan-commits] [Git][darshan/darshan][master] 2 commits: include LaTeX Perl module and install them

Shane Snyder xgitlab at cels.anl.gov
Wed Sep 2 13:05:39 CDT 2020



Shane Snyder pushed to branch master at darshan / darshan


Commits:
6915b32f by Shane Snyder at 2020-09-02T18:00:57+00:00
include LaTeX Perl module and install them

- - - - -
01f3672e by Shane Snyder at 2020-09-02T13:05:28-05:00
Merge branch 'dev-darshanutil-perl-pod-install' into 'master'

include LaTeX Perl module and install with darshan-util

Closes #279

See merge request darshan/darshan!61
- - - - -


3 changed files:

- darshan-util/Makefile.in
- + darshan-util/darshan-job-summary/lib/Pod/Constants.pm
- + darshan-util/darshan-job-summary/lib/Pod/LaTeX.pm


Changes:

=====================================
darshan-util/Makefile.in
=====================================
@@ -224,6 +224,9 @@ endif
 	install -d $(DESTDIR)$(libdir)/Number
 	install -d $(DESTDIR)$(libdir)/Number/Bytes
 	install -m 644 $(srcdir)/darshan-job-summary/lib/Number/Bytes/Human.pm $(DESTDIR)$(libdir)/Number/Bytes
+	install -d $(DESTDIR)$(libdir)/Pod
+	install -m 644 $(srcdir)/darshan-job-summary/lib/Pod/Constants.pm $(DESTDIR)$(libdir)/Pod/
+	install -m 644 $(srcdir)/darshan-job-summary/lib/Pod/LaTeX.pm $(DESTDIR)$(libdir)/Pod/
 	install -d $(DESTDIR)$(datarootdir)
 	install -m 644 $(srcdir)/darshan-job-summary/share/* $(DESTDIR)$(datarootdir)
 	install -d $(DESTDIR)$(libdir)/pkgconfig


=====================================
darshan-util/darshan-job-summary/lib/Pod/Constants.pm
=====================================
@@ -0,0 +1,468 @@
+package Pod::Constants;
+
+use 5.006002;
+use strict;
+use warnings;
+
+use base qw(Pod::Parser Exporter);
+use Carp;
+
+our $VERSION = 0.19;
+
+# An ugly hack to go from caller() to the relevant parser state
+# variable
+my %parsers;
+
+sub end_input {
+	#my ($parser, $command, $paragraph, $line_num) = (@_);
+	my $parser = shift;
+
+	return unless $parser->{active};
+
+	print "Found end of $parser->{active}\n" if $parser->{DEBUG};
+	my $whereto = $parser->{wanted_pod_tags}->{$parser->{active}};
+	print "\$_ will be set to:\n---\n$parser->{paragraphs}\n---\n" if $parser->{DEBUG};
+
+	$parser->{paragraphs} =~ s/^\s*|\s*$//gs if $parser->{trimmed_tags}->{$parser->{active}};
+
+	if (ref $whereto eq 'CODE') {
+		print "calling sub\n" if $parser->{DEBUG};
+		local ($_) = $parser->{paragraphs};
+		$whereto->();
+		print "done\n" if $parser->{DEBUG};
+	} elsif (ref $whereto eq 'SCALAR') {
+		print "inserting into scalar\n" if $parser->{DEBUG};
+		$$whereto = $parser->{paragraphs};
+	} elsif (ref $whereto eq 'ARRAY') {
+		print "inserting into array\n" if $parser->{DEBUG};
+		@$whereto = split /\n/, $parser->{paragraphs};
+	} elsif (ref $whereto eq 'HASH') {
+		print "inserting into hash\n" if $parser->{DEBUG};
+		# Oh, sorry, should I be in LISP101?
+		%$whereto = (
+			map { map { s/^\s*|\s*$//g; $_ } split /=>/ } grep m/^
+					 ( (?:[^=]|=[^>])+ )   # scan up to "=>"
+					 =>
+					 ( (?:[^=]|=[^>])+ =? )# don't allow more "=>"'s
+					 $/x, split /\n/, $parser->{paragraphs},);
+	} else { die $whereto }
+	$parser->{active} = undef;
+}
+
+# Pod::Parser overloaded command
+sub command {
+	my ($parser, $command, $paragraph, $line_num) = @_;
+
+	$paragraph =~ s/(?:\r\n|\n\r)/\n/g;
+
+	print "Got command =$command, value=$paragraph\n" if $parser->{DEBUG};
+
+	$parser->end_input() if $parser->{active};
+
+	my ($lookup);
+	# first check for a catch-all for this command type
+	if ( exists $parser->{wanted_pod_tags}->{"*$command"} ) {
+		$parser->{paragraphs} = $paragraph;
+		$parser->{active} = "*$command";
+	} elsif ($command =~ m/^(head\d+|item|(for|begin))$/) {
+		if ( $2 ) {
+			# if it's a "for" or "begin" section, the title is the
+			# first word only
+			($lookup, $parser->{paragraphs}) = $paragraph =~ m/^\s*(\S*)\s*(.*)/s;
+		} else {
+			# otherwise, it's up to the end of the line
+			($lookup, $parser->{paragraphs}) = $paragraph =~ m/^\s*(\S[^\n]*?)\s*\n(.*)$/s;
+		}
+
+		# Look for a match by name
+		if (defined $lookup && exists $parser->{wanted_pod_tags}->{$lookup}) {
+			print "Found $lookup\n" if ($parser->{DEBUG});
+			$parser->{active} = $lookup;
+		} elsif ($parser->{DEBUG}) {
+			local $^W = 0;
+			print "Ignoring =$command $paragraph (lookup = $lookup)\n"
+		}
+
+	} else {
+		# nothing
+		print "Ignoring =$command (not known)\n" if $parser->{DEBUG};
+	}
+}
+
+# Pod::Parser overloaded verbatim
+sub verbatim {
+	my ($parser, $paragraph, $line_num) = @_;
+	$paragraph =~ s/(?:\r\n|\n\r)/\n/g;
+
+	my $status = $parser->{active} ? 'using' : 'ignoring';
+	print "Got paragraph: $paragraph ($status)\n" if $parser->{DEBUG};
+
+	$parser->{paragraphs} .= $paragraph if defined $parser->{active}
+}
+
+# Pod::Parser overloaded textblock
+sub textblock { goto \&verbatim }
+
+sub import {
+	my $class = shift;
+
+	# if no args, just return
+	return unless (@_);
+
+	# try to guess the source file of the caller
+	my $source_file;
+	if (caller ne 'main') {
+		(my $module = caller.'.pm') =~ s|::|/|g;
+		$source_file = $INC{$module};
+	}
+	$source_file ||= $0;
+
+	croak "Cannot find source file (guessed $source_file) for package ".caller unless -f $source_file;
+
+	# nasty tricks with the stack so we don't have to be silly with
+	# caller()
+	unshift @_, $source_file;
+	goto \&import_from_file;
+}
+
+sub import_from_file {
+	my $filename = shift;
+
+	my $parser = __PACKAGE__->new();
+
+	$parser->{wanted_pod_tags} = {};
+	$parser->{trimmed_tags} = {};
+	$parser->{trim_next} = 0;
+	$parser->{DEBUG} = 0;
+	$parser->{active} = undef;
+	$parsers{caller()} = $parser;
+
+	$parser->add_hook(@_);
+
+	print "Pod::Parser: DEBUG: Opening $filename for reading\n" if $parser->{DEBUG};
+	open my $fh, '<', $filename or croak "cannot open $filename for reading; $!";
+
+	$parser->parse_from_filehandle($fh, \*STDOUT);
+
+	close $fh;
+}
+
+sub add_hook {
+	my $parser;
+	if (eval { $_[0]->isa(__PACKAGE__) }) {
+		$parser = shift;
+	} else {
+		$parser = $parsers{caller()} or croak 'add_hook called, but don\'t know what for - caller = '.caller;
+	}
+	while (my ($pod_tag, $var) = splice @_, 0, 2) {
+		#print "$pod_tag: $var\n";
+		if (lc($pod_tag) eq '-trim') {
+			$parser->{trim_next} = $var;
+		} elsif ( lc($pod_tag) eq '-debug' ) {
+			$parser->{DEBUG} = $var;
+		} elsif (lc($pod_tag) eq '-usage') {
+			# an idea for later - automatic "usage"
+			#%wanted_pod_tags{@tags}
+		} else {
+			if ((ref $var) =~ /^(?:SCALAR|CODE|ARRAY|HASH)$/) {
+				print "Will look for $pod_tag.\n" if $parser->{DEBUG};
+				$parser->{wanted_pod_tags}->{$pod_tag} = $var;
+				$parser->{trimmed_tags}->{$pod_tag} = 1 if $parser->{trim_next};
+			} else {
+				croak "Sorry - need a reference to import POD sections into, not the scalar value $var"
+			}
+		}
+	}
+}
+
+sub delete_hook {
+	my $parser;
+	if (eval { $_[0]->isa(__PACKAGE__) }) {
+		$parser = shift;
+	} else {
+		$parser = $parsers{caller()} or croak 'delete_hook called, but don\'t know what for - caller = '.caller;
+	}
+	while ( my $label = shift ) {
+		delete $parser->{wanted_pod_tags}->{$label};
+		delete $parser->{trimmed_tags}->{$label};
+	}
+}
+
+1;
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+Pod::Constants - Include constants from POD
+
+=head1 SYNOPSIS
+
+ our ($myvar, $VERSION, @myarray, $html, %myhash);
+
+ use Pod::Constants -trim => 1,
+     'Pod Section Name' => \$myvar,
+     'Version' => sub { eval },
+     'Some list' => \@myarray,
+     html => \$html,
+     'Some hash' => \%myhash;
+
+ =head2 Pod Section Name
+
+ This string will be loaded into $myvar
+
+ =head2 Version
+
+ # This is an example of using a closure.  $_ is set to the
+ # contents of the paragraph.  In this example, "eval" is
+ # used to execute this code at run time.
+ $VERSION = 0.19;
+
+ =head2 Some list
+
+ Each line from this section of the file
+ will be placed into a separate array element.
+ For example, this is $myarray[2].
+
+ =head2 Some hash
+
+ This text will not go into the hash, because
+ it doesn't look like a definition list.
+     key1 => Some value (this will go into the hash)
+     var2 => Some Other value (so will this)
+     wtf = This won't make it in.
+
+ =head2 %myhash's value after the above:
+
+    ( key1 => "Some value (this will go into the hash)",
+      var2 => "Some Other value (so will this)"          )
+
+ =begin html <p>This text will be in $html</p>
+
+ =cut
+
+=head1 DESCRIPTION
+
+This module allows you to specify those constants that should be
+documented in your POD, and pull them out a run time in a fairly
+arbitrary fashion.
+
+Pod::Constants uses Pod::Parser to do the parsing of the source file.
+It has to open the source file it is called from, and does so directly
+either by lookup in %INC or by assuming it is $0 if the caller is
+"main" (or it can't find %INC{caller()})
+
+=head2 ARBITARY DECISIONS
+
+I have made this code only allow the "Pod Section Name" to match
+`headN', `item', `for' and `begin' POD sections.  If you have a good
+reason why you think it should match other POD sections, drop me a
+line and if I'm convinced I'll put it in the standard version.
+
+For `for' and `begin' sections, only the first word is counted as
+being a part of the specifier, as opposed to `headN' and `item', where
+the entire rest of the line counts.
+
+=head1 FUNCTIONS
+
+=head2 import(@args)
+
+This function is called when we are "use"'d.  It determines the source
+file by inspecting the value of caller() or $0.
+
+The form of @args is HOOK => $where.
+
+$where may be a scalar reference, in which case the contents of the
+POD section called "HOOK" will be loaded into $where.
+
+$where may be an array reference, in which case the contents of the
+array will be the contents of the POD section called "HOOK", split
+into lines.
+
+$where may be a hash reference, in which case any lines with a "=>"
+symbol present will have everything on the left have side of the =>
+operator as keys and everything on the right as values.  You do not
+need to quote either, nor have trailing commas at the end of the
+lines.
+
+$where may be a code reference (sub { }), in which case the sub is
+called when the hook is encountered.  $_ is set to the value of the
+POD paragraph.
+
+You may also specify the behaviour of whitespace trimming; by default,
+no trimming is done except on the HOOK names.  Setting "-trim => 1"
+turns on a package "global" (until the next time import is called)
+that will trim the $_ sent for processing by the hook processing
+function (be it a given function, or the built-in array/hash
+splitters) for leading and trailing whitespace.
+
+The name of HOOK is matched against any "=head1", "=head2", "=item",
+"=for", "=begin" value.  If you specify the special hooknames "*item",
+"*head1", etc, then you will get a function that is run for every 
+
+Note that the supplied functions for array and hash splitting are
+exactly equivalent to fairly simple Perl blocks:
+
+Array:
+
+  HOOK => sub { @array = split /\n/, $_ }
+
+Hash:
+
+  HOOK => sub {
+  %hash =
+      (map { map { s/^\s+|\s+$//g; $_ } split /=>/, $_ }
+        (grep m/^
+            ( (?:[^=]|=[^>])+ )   # scan up to "=>"
+            =>
+            ( (?:[^=]|=[^>])+ =? )# don't allow more "=>"'s
+            $/x, split /\n/, $_));
+  }
+
+Well, they're simple if you can grok map, a regular expression like
+that and a functional programming style.  If you can't I'm sure it is
+probably voodoo to you.
+
+Here's the procedural equivalent:
+
+  HOOK => sub {
+     for my $line (split /\n/, $_) {
+         my ($key, $value, $junk) = split /=>/, $line;
+         next if $junk;
+         $key =~ s/^\s+|\s+$//g
+         $value =~ s/^\s+|\s+$//g
+         $hash{$key} = $value;
+     }
+  },
+
+=head2 import_from_file($filename, @args)
+
+Very similar to straight "import", but you specify the source filename
+explicitly.
+
+=head2 add_hook(NAME => value)
+
+This function adds another hook, it is useful for dynamic updating of
+parsing through the document.
+
+For an example, please see t/01-constants.t in the source
+distribution.  More detailed examples will be added in a later
+release.
+
+=head2 delete_hook(@list)
+
+Deletes the named hooks.  Companion function to add_hook
+
+=head2 CLOSURES AS DESTINATIONS
+
+If the given value is a ref CODE, then that function is called, with
+$_ set to the value of the paragraph.  This can be very useful for
+applying your own custom mutations to the POD to change it from human
+readable text into something your program can use.
+
+After I added this function, I just kept on thinking of cool uses for
+it.  The nice, succinct code you can make with it is one of
+Pod::Constant's strongest features.
+
+Below are some examples.
+
+=head1 EXAMPLES
+
+=head2 Module Makefile.PL maintenance
+
+Tired of keeping those module Makefile.PL's up to date?  Note: This
+method seems to break dh-make-perl.
+
+=head2 Example Makefile.PL
+
+ eval "use Pod::Constants";
+ ($Pod::Constants::VERSION >= 0.11)
+     or die <<EOF
+ ####
+ ####  ERROR: This module requires Pod::Constants 0.11 or
+ ####  higher to be installed.
+ ####
+ EOF
+
+ my ($VERSION, $NAME, $PREREQ_PM, $ABSTRACT, $AUTHOR);
+ Pod::Constants::import_from_file 
+     (
+      'MyTestModule.pm',
+      'MODULE RELEASE' => sub { ($VERSION) = m/(\d+\.\d+)/ },
+      'DEPENDENCIES' => ($PREREQ_PM = { }),
+       -trim => 1,
+      'NAME' => sub { $ABSTRACT=$_; ($NAME) = m/(\S+)/ },
+      'AUTHOR' => \$AUTHOR,
+     );
+
+ WriteMakefile
+     (
+      'NAME'        => $NAME,
+      'PREREQ_PM'        => $PREREQ_PM,
+      'VERSION'          => $VERSION,
+      ($] >= 5.005 ?    ## Add these new keywords supported since 5.005
+       (ABSTRACT         => $ABSTRACT,
+        AUTHOR           => $AUTHOR) : ()),
+     );
+
+=head2 Corresponding Module
+
+ =head1 NAME
+
+ MyTestModule - Demonstrate Pod::Constant's Makefile.PL usefulness
+
+ =head2 MODULE RELEASE
+
+ This is release 1.05 of this module.
+
+ =head2 DEPENDENCIES
+
+ The following modules are required to make this module:
+
+    Some::Module => 0.02
+
+ =head2 AUTHOR
+
+ Ima Twat <ima at twat.name>
+
+ =cut
+
+ our $VERSION;
+ use Pod::Constants -trim => 1,
+     'MODULE RELEASE' => sub { ($VERSION) = m/(\d+\.\d+) or die };
+
+=head1 AUTHOR
+
+Sam Vilain, <samv at cpan.org>
+
+Maintained by Marius Gavrilescu, <marius at ieval.ro> since July 2015
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2001, 2002, 2007 Sam Vilain. All Rights Reserved.
+
+Copyright (C) 2015-2016 by Marius Gavrilescu <marius at ieval.ro>.
+
+This module is free software. It may be used, redistributed and/or
+modified under the terms of the Perl Artistic License, version 2.
+
+See the LICENSE file in the root of this distribution for a copy of
+the Perl Artistic License, version 2.
+
+=head1 BUGS/TODO
+
+I keep thinking it would be nice to be able to import an =item list
+into an array or something, eg for a program argument list.  But I'm
+not too sure how it would be all that useful in practice; you'd end up
+putting the function names for callbacks in the pod or something
+(perhaps not all that bad).
+
+Would this be useful?
+
+ Pod::Constants::import(Foo::SECTION => \$myvar);
+
+Debug output is not very readable
+
+
+=cut


=====================================
darshan-util/darshan-job-summary/lib/Pod/LaTeX.pm
=====================================
@@ -0,0 +1,1883 @@
+package Pod::LaTeX;
+
+=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 if $] > 5.017, 'deprecate';
+
+# use Data::Dumper; # for debugging
+use Carp;
+
+use vars qw/ $VERSION %HTML_Escapes @LatexSections /;
+
+$VERSION = '0.61';
+
+# Definitions of =headN -> latex mapping
+ at LatexSections = (qw/
+		  chapter
+		  section
+		  subsection
+		  subsubsection
+		  paragraph
+		  subparagraph
+		  /);
+
+# Standard escape sequences converted to Latex.
+# The Unicode name of each character is given in the comments.
+# Complete LaTeX set added by Peter Acklam.
+
+%HTML_Escapes = (
+     'sol'    => '\textfractionsolidus{}',  # xxx - or should it be just '/'
+     'verbar' => '|',
+
+     # The stuff below is based on the information available at
+     # http://www.w3.org/TR/html401/sgml/entities.html
+
+     # All characters in the range 0xA0-0xFF of the ISO 8859-1 character set.
+     # Several of these characters require the `textcomp' LaTeX package.
+     'nbsp'   => q|~|,                     # 0xA0 - no-break space = non-breaking space
+     'iexcl'  => q|\textexclamdown{}|,     # 0xA1 - inverted exclamation mark
+     'cent'   => q|\textcent{}|,           # 0xA2 - cent sign
+     'pound'  => q|\textsterling{}|,       # 0xA3 - pound sign
+     'curren' => q|\textcurrency{}|,       # 0xA4 - currency sign
+     'yen'    => q|\textyen{}|,            # 0xA5 - yen sign = yuan sign
+     'brvbar' => q|\textbrokenbar{}|,      # 0xA6 - broken bar = broken vertical bar
+     'sect'   => q|\textsection{}|,        # 0xA7 - section sign
+     'uml'    => q|\textasciidieresis{}|,  # 0xA8 - diaeresis = spacing diaeresis
+     'copy'   => q|\textcopyright{}|,      # 0xA9 - copyright sign
+     'ordf'   => q|\textordfeminine{}|,    # 0xAA - feminine ordinal indicator
+     'laquo'  => q|\guillemotleft{}|,      # 0xAB - left-pointing double angle quotation mark = left pointing guillemet
+     'not'    => q|\textlnot{}|,           # 0xAC - not sign
+     'shy'    => q|\-|,                    # 0xAD - soft hyphen = discretionary hyphen
+     'reg'    => q|\textregistered{}|,     # 0xAE - registered sign = registered trade mark sign
+     'macr'   => q|\textasciimacron{}|,    # 0xAF - macron = spacing macron = overline = APL overbar
+     'deg'    => q|\textdegree{}|,         # 0xB0 - degree sign
+     'plusmn' => q|\textpm{}|,             # 0xB1 - plus-minus sign = plus-or-minus sign
+     'sup2'   => q|\texttwosuperior{}|,    # 0xB2 - superscript two = superscript digit two = squared
+     'sup3'   => q|\textthreesuperior{}|,  # 0xB3 - superscript three = superscript digit three = cubed
+     'acute'  => q|\textasciiacute{}|,     # 0xB4 - acute accent = spacing acute
+     'micro'  => q|\textmu{}|,             # 0xB5 - micro sign
+     'para'   => q|\textparagraph{}|,      # 0xB6 - pilcrow sign = paragraph sign
+     'middot' => q|\textperiodcentered{}|, # 0xB7 - middle dot = Georgian comma = Greek middle dot
+     'cedil'  => q|\c{}|,                  # 0xB8 - cedilla = spacing cedilla
+     'sup1'   => q|\textonesuperior{}|,    # 0xB9 - superscript one = superscript digit one
+     'ordm'   => q|\textordmasculine{}|,   # 0xBA - masculine ordinal indicator
+     'raquo'  => q|\guillemotright{}|,     # 0xBB - right-pointing double angle quotation mark = right pointing guillemet
+     'frac14' => q|\textonequarter{}|,     # 0xBC - vulgar fraction one quarter = fraction one quarter
+     'frac12' => q|\textonehalf{}|,        # 0xBD - vulgar fraction one half = fraction one half
+     'frac34' => q|\textthreequarters{}|,  # 0xBE - vulgar fraction three quarters = fraction three quarters
+     'iquest' => q|\textquestiondown{}|,   # 0xBF - inverted question mark = turned question mark
+     'Agrave' => q|\`A|,                   # 0xC0 - latin capital letter A with grave = latin capital letter A grave
+     'Aacute' => q|\'A|,             # 0xC1 - latin capital letter A with acute
+     'Acirc'  => q|\^A|,             # 0xC2 - latin capital letter A with circumflex
+     'Atilde' => q|\~A|,             # 0xC3 - latin capital letter A with tilde
+     'Auml'   => q|\"A|,             # 0xC4 - latin capital letter A with diaeresis
+     'Aring'  => q|\AA{}|,           # 0xC5 - latin capital letter A with ring above = latin capital letter A ring
+     'AElig'  => q|\AE{}|,           # 0xC6 - latin capital letter AE = latin capital ligature AE
+     'Ccedil' => q|\c{C}|,           # 0xC7 - latin capital letter C with cedilla
+     'Egrave' => q|\`E|,             # 0xC8 - latin capital letter E with grave
+     'Eacute' => q|\'E|,             # 0xC9 - latin capital letter E with acute
+     'Ecirc'  => q|\^E|,             # 0xCA - latin capital letter E with circumflex
+     'Euml'   => q|\"E|,             # 0xCB - latin capital letter E with diaeresis
+     'Igrave' => q|\`I|,             # 0xCC - latin capital letter I with grave
+     'Iacute' => q|\'I|,             # 0xCD - latin capital letter I with acute
+     'Icirc'  => q|\^I|,             # 0xCE - latin capital letter I with circumflex
+     'Iuml'   => q|\"I|,             # 0xCF - latin capital letter I with diaeresis
+     'ETH'    => q|\DH{}|,           # 0xD0 - latin capital letter ETH
+     'Ntilde' => q|\~N|,             # 0xD1 - latin capital letter N with tilde
+     'Ograve' => q|\`O|,             # 0xD2 - latin capital letter O with grave
+     'Oacute' => q|\'O|,             # 0xD3 - latin capital letter O with acute
+     'Ocirc'  => q|\^O|,             # 0xD4 - latin capital letter O with circumflex
+     'Otilde' => q|\~O|,             # 0xD5 - latin capital letter O with tilde
+     'Ouml'   => q|\"O|,             # 0xD6 - latin capital letter O with diaeresis
+     'times'  => q|\texttimes{}|,    # 0xD7 - multiplication sign
+     'Oslash' => q|\O{}|,            # 0xD8 - latin capital letter O with stroke = latin capital letter O slash
+     'Ugrave' => q|\`U|,             # 0xD9 - latin capital letter U with grave
+     'Uacute' => q|\'U|,             # 0xDA - latin capital letter U with acute
+     'Ucirc'  => q|\^U|,             # 0xDB - latin capital letter U with circumflex
+     'Uuml'   => q|\"U|,             # 0xDC - latin capital letter U with diaeresis
+     'Yacute' => q|\'Y|,             # 0xDD - latin capital letter Y with acute
+     'THORN'  => q|\TH{}|,           # 0xDE - latin capital letter THORN
+     'szlig'  => q|\ss{}|,           # 0xDF - latin small letter sharp s = ess-zed
+     'agrave' => q|\`a|,             # 0xE0 - latin small letter a with grave = latin small letter a grave
+     'aacute' => q|\'a|,             # 0xE1 - latin small letter a with acute
+     'acirc'  => q|\^a|,             # 0xE2 - latin small letter a with circumflex
+     'atilde' => q|\~a|,             # 0xE3 - latin small letter a with tilde
+     'auml'   => q|\"a|,             # 0xE4 - latin small letter a with diaeresis
+     'aring'  => q|\aa{}|,           # 0xE5 - latin small letter a with ring above = latin small letter a ring
+     'aelig'  => q|\ae{}|,           # 0xE6 - latin small letter ae = latin small ligature ae
+     'ccedil' => q|\c{c}|,           # 0xE7 - latin small letter c with cedilla
+     'egrave' => q|\`e|,             # 0xE8 - latin small letter e with grave
+     'eacute' => q|\'e|,             # 0xE9 - latin small letter e with acute
+     'ecirc'  => q|\^e|,             # 0xEA - latin small letter e with circumflex
+     'euml'   => q|\"e|,             # 0xEB - latin small letter e with diaeresis
+     'igrave' => q|\`i|,             # 0xEC - latin small letter i with grave
+     'iacute' => q|\'i|,             # 0xED - latin small letter i with acute
+     'icirc'  => q|\^i|,             # 0xEE - latin small letter i with circumflex
+     'iuml'   => q|\"i|,             # 0xEF - latin small letter i with diaeresis
+     'eth'    => q|\dh{}|,           # 0xF0 - latin small letter eth
+     'ntilde' => q|\~n|,             # 0xF1 - latin small letter n with tilde
+     'ograve' => q|\`o|,             # 0xF2 - latin small letter o with grave
+     'oacute' => q|\'o|,             # 0xF3 - latin small letter o with acute
+     'ocirc'  => q|\^o|,             # 0xF4 - latin small letter o with circumflex
+     'otilde' => q|\~o|,             # 0xF5 - latin small letter o with tilde
+     'ouml'   => q|\"o|,             # 0xF6 - latin small letter o with diaeresis
+     'divide' => q|\textdiv{}|,      # 0xF7 - division sign
+     'oslash' => q|\o{}|,            # 0xF8 - latin small letter o with stroke, = latin small letter o slash
+     'ugrave' => q|\`u|,             # 0xF9 - latin small letter u with grave
+     'uacute' => q|\'u|,             # 0xFA - latin small letter u with acute
+     'ucirc'  => q|\^u|,             # 0xFB - latin small letter u with circumflex
+     'uuml'   => q|\"u|,             # 0xFC - latin small letter u with diaeresis
+     'yacute' => q|\'y|,             # 0xFD - latin small letter y with acute
+     'thorn'  => q|\th{}|,           # 0xFE - latin small letter thorn
+     'yuml'   => q|\"y|,             # 0xFF - latin small letter y with diaeresis
+
+     # Latin Extended-B
+     'fnof'   => q|\textflorin{}|,   # latin small f with hook = function = florin
+
+     # Greek
+     'Alpha'    => q|$\mathrm{A}$|,      # greek capital letter alpha
+     'Beta'     => q|$\mathrm{B}$|,      # greek capital letter beta
+     'Gamma'    => q|$\Gamma$|,          # greek capital letter gamma
+     'Delta'    => q|$\Delta$|,          # greek capital letter delta
+     'Epsilon'  => q|$\mathrm{E}$|,      # greek capital letter epsilon
+     'Zeta'     => q|$\mathrm{Z}$|,      # greek capital letter zeta
+     'Eta'      => q|$\mathrm{H}$|,      # greek capital letter eta
+     'Theta'    => q|$\Theta$|,          # greek capital letter theta
+     'Iota'     => q|$\mathrm{I}$|,      # greek capital letter iota
+     'Kappa'    => q|$\mathrm{K}$|,      # greek capital letter kappa
+     'Lambda'   => q|$\Lambda$|,         # greek capital letter lambda
+     'Mu'       => q|$\mathrm{M}$|,      # greek capital letter mu
+     'Nu'       => q|$\mathrm{N}$|,      # greek capital letter nu
+     'Xi'       => q|$\Xi$|,             # greek capital letter xi
+     'Omicron'  => q|$\mathrm{O}$|,      # greek capital letter omicron
+     'Pi'       => q|$\Pi$|,             # greek capital letter pi
+     'Rho'      => q|$\mathrm{R}$|,      # greek capital letter rho
+     'Sigma'    => q|$\Sigma$|,          # greek capital letter sigma
+     'Tau'      => q|$\mathrm{T}$|,      # greek capital letter tau
+     'Upsilon'  => q|$\Upsilon$|,        # greek capital letter upsilon
+     'Phi'      => q|$\Phi$|,            # greek capital letter phi
+     'Chi'      => q|$\mathrm{X}$|,      # greek capital letter chi
+     'Psi'      => q|$\Psi$|,            # greek capital letter psi
+     'Omega'    => q|$\Omega$|,          # greek capital letter omega
+
+     'alpha'    => q|$\alpha$|,          # greek small letter alpha
+     'beta'     => q|$\beta$|,           # greek small letter beta
+     'gamma'    => q|$\gamma$|,          # greek small letter gamma
+     'delta'    => q|$\delta$|,          # greek small letter delta
+     'epsilon'  => q|$\epsilon$|,        # greek small letter epsilon
+     'zeta'     => q|$\zeta$|,           # greek small letter zeta
+     'eta'      => q|$\eta$|,            # greek small letter eta
+     'theta'    => q|$\theta$|,          # greek small letter theta
+     'iota'     => q|$\iota$|,           # greek small letter iota
+     'kappa'    => q|$\kappa$|,          # greek small letter kappa
+     'lambda'   => q|$\lambda$|,         # greek small letter lambda
+     'mu'       => q|$\mu$|,             # greek small letter mu
+     'nu'       => q|$\nu$|,             # greek small letter nu
+     'xi'       => q|$\xi$|,             # greek small letter xi
+     'omicron'  => q|$o$|,               # greek small letter omicron
+     'pi'       => q|$\pi$|,             # greek small letter pi
+     'rho'      => q|$\rho$|,            # greek small letter rho
+#    'sigmaf'   => q||,                  # greek small letter final sigma
+     'sigma'    => q|$\sigma$|,          # greek small letter sigma
+     'tau'      => q|$\tau$|,            # greek small letter tau
+     'upsilon'  => q|$\upsilon$|,        # greek small letter upsilon
+     'phi'      => q|$\phi$|,            # greek small letter phi
+     'chi'      => q|$\chi$|,            # greek small letter chi
+     'psi'      => q|$\psi$|,            # greek small letter psi
+     'omega'    => q|$\omega$|,          # greek small letter omega
+#    'thetasym' => q||,                  # greek small letter theta symbol
+#    'upsih'    => q||,                  # greek upsilon with hook symbol
+#    'piv'      => q||,                  # greek pi symbol
+
+     # General Punctuation
+     'bull'     => q|\textbullet{}|,     # bullet = black small circle
+     # bullet is NOT the same as bullet operator
+     'hellip'   => q|\textellipsis{}|,           # horizontal ellipsis = three dot leader
+     'prime'    => q|\textquotesingle{}|,        # prime = minutes = feet
+     'Prime'    => q|\textquotedbl{}|,           # double prime = seconds = inches
+     'oline'    => q|\textasciimacron{}|,        # overline = spacing overscore
+     'frasl'    => q|\textfractionsolidus{}|,    # fraction slash
+
+     # Letterlike Symbols
+     'weierp'   => q|$\wp$|,                     # script capital P = power set = Weierstrass p
+     'image'    => q|$\Re$|,                     # blackletter capital I = imaginary part
+     'real'     => q|$\Im$|,                     # blackletter capital R = real part symbol
+     'trade'    => q|\texttrademark{}|,          # trade mark sign
+#    'alefsym'  => q||,                          # alef symbol = first transfinite cardinal
+     # alef symbol is NOT the same as hebrew letter alef, although the same
+     # glyph could be used to depict both characters
+
+     # Arrows
+     'larr'     => q|\textleftarrow{}|,          # leftwards arrow
+     'uarr'     => q|\textuparrow{}|,            # upwards arrow
+     'rarr'     => q|\textrightarrow{}|,         # rightwards arrow
+     'darr'     => q|\textdownarrow{}|,          # downwards arrow
+     'harr'     => q|$\leftrightarrow$|,         # left right arrow
+#    'crarr'    => q||,                          # downwards arrow with corner leftwards = carriage return
+     'lArr'     => q|$\Leftarrow$|,              # leftwards double arrow
+     # ISO 10646 does not say that lArr is the same as the 'is implied by'
+     # arrow but also does not have any other character for that function. So
+     # lArr can be used for 'is implied by' as ISOtech suggests
+     'uArr'     => q|$\Uparrow$|,                # upwards double arrow
+     'rArr'     => q|$\Rightarrow$|,             # rightwards double arrow
+     # ISO 10646 does not say this is the 'implies' character but does not
+     # have another character with this function so ? rArr can be used for
+     # 'implies' as ISOtech suggests
+     'dArr'     => q|$\Downarrow$|,              # downwards double arrow
+     'hArr'     => q|$\Leftrightarrow$|,         # left right double arrow
+
+     # Mathematical Operators.
+     # Some of these require the `amssymb' package.
+     'forall'   => q|$\forall$|,                 # for all
+     'part'     => q|$\partial$|,                # partial differential
+     'exist'    => q|$\exists$|,                 # there exists
+     'empty'    => q|$\emptyset$|,               # empty set = null set = diameter
+     'nabla'    => q|$\nabla$|,                  # nabla = backward difference
+     'isin'     => q|$\in$|,                     # element of
+     'notin'    => q|$\notin$|,                  # not an element of
+     'ni'       => q|$\ni$|,                     # contains as member
+     'prod'     => q|$\prod$|,                   # n-ary product = product sign
+     # prod is NOT the same character as 'greek capital letter pi' though the
+     # same glyph might be used for both
+     'sum'      => q|$\sum$|,                    # n-ary summation
+     # sum is NOT the same character as 'greek capital letter sigma' though
+     # the same glyph might be used for both
+     'minus'    => q|$-$|,                       # minus sign
+     'lowast'   => q|$\ast$|,                    # asterisk operator
+     'radic'    => q|$\surd$|,                   # square root = radical sign
+     'prop'     => q|$\propto$|,                 # proportional to
+     'infin'    => q|$\infty$|,                  # infinity
+     'ang'      => q|$\angle$|,                  # angle
+     'and'      => q|$\wedge$|,                  # logical and = wedge
+     'or'       => q|$\vee$|,                    # logical or = vee
+     'cap'      => q|$\cap$|,                    # intersection = cap
+     'cup'      => q|$\cup$|,                    # union = cup
+     'int'      => q|$\int$|,                    # integral
+     'there4'   => q|$\therefore$|,              # therefore
+     'sim'      => q|$\sim$|,                    # tilde operator = varies with = similar to
+     # tilde operator is NOT the same character as the tilde
+     'cong'     => q|$\cong$|,                   # approximately equal to
+     'asymp'    => q|$\asymp$|,                  # almost equal to = asymptotic to
+     'ne'       => q|$\neq$|,                    # not equal to
+     'equiv'    => q|$\equiv$|,                  # identical to
+     'le'       => q|$\leq$|,                    # less-than or equal to
+     'ge'       => q|$\geq$|,                    # greater-than or equal to
+     'sub'      => q|$\subset$|,                 # subset of
+     'sup'      => q|$\supset$|,                 # superset of
+     # note that nsup, 'not a superset of' is not covered by the Symbol font
+     # encoding and is not included.
+     'nsub'     => q|$\not\subset$|,             # not a subset of
+     'sube'     => q|$\subseteq$|,               # subset of or equal to
+     'supe'     => q|$\supseteq$|,               # superset of or equal to
+     'oplus'    => q|$\oplus$|,                  # circled plus = direct sum
+     'otimes'   => q|$\otimes$|,                 # circled times = vector product
+     'perp'     => q|$\perp$|,                   # up tack = orthogonal to = perpendicular
+     'sdot'     => q|$\cdot$|,                   # dot operator
+     # dot operator is NOT the same character as middle dot
+
+     # Miscellaneous Technical
+     'lceil'    => q|$\lceil$|,                  # left ceiling = apl upstile
+     'rceil'    => q|$\rceil$|,                  # right ceiling
+     'lfloor'   => q|$\lfloor$|,                 # left floor = apl downstile
+     'rfloor'   => q|$\rfloor$|,                 # right floor
+     'lang'     => q|$\langle$|,                 # left-pointing angle bracket = bra
+     # lang is NOT the same character as 'less than' or 'single left-pointing
+     # angle quotation mark'
+     'rang'     => q|$\rangle$|,                 # right-pointing angle bracket = ket
+     # rang is NOT the same character as 'greater than' or 'single
+     # right-pointing angle quotation mark'
+
+     # Geometric Shapes
+     'loz'      => q|$\lozenge$|,                # lozenge
+
+     # Miscellaneous Symbols
+     'spades'   => q|$\spadesuit$|,              # black spade suit
+     'clubs'    => q|$\clubsuit$|,               # black club suit = shamrock
+     'hearts'   => q|$\heartsuit$|,              # black heart suit = valentine
+     'diams'    => q|$\diamondsuit$|,            # black diamond suit
+
+     # C0 Controls and Basic Latin
+     'quot'     => q|"|,                         # quotation mark = APL quote ["]
+     'amp'      => q|\&|,                        # ampersand
+     'lt'       => q|<|,                         # less-than sign
+     'gt'       => q|>|,                         # greater-than sign
+     'OElig'    => q|\OE{}|,                     # latin capital ligature OE
+     'oelig'    => q|\oe{}|,                     # latin small ligature oe
+     'Scaron'   => q|\v{S}|,                     # latin capital letter S with caron
+     'scaron'   => q|\v{s}|,                     # latin small letter s with caron
+     'Yuml'     => q|\"Y|,                       # latin capital letter Y with diaeresis
+     'circ'     => q|\textasciicircum{}|,        # modifier letter circumflex accent
+     'tilde'    => q|\textasciitilde{}|,         # small tilde
+     'ensp'     => q|\phantom{n}|,               # en space
+     'emsp'     => q|\hspace{1em}|,              # em space
+     'thinsp'   => q|\,|,                        # thin space
+     'zwnj'     => q|{}|,                        # zero width non-joiner
+#    'zwj'      => q||,                          # zero width joiner
+#    'lrm'      => q||,                          # left-to-right mark
+#    'rlm'      => q||,                          # right-to-left mark
+     'ndash'    => q|--|,                        # en dash
+     'mdash'    => q|---|,                       # em dash
+     'lsquo'    => q|\textquoteleft{}|,          # left single quotation mark
+     'rsquo'    => q|\textquoteright{}|,         # right single quotation mark
+     'sbquo'    => q|\quotesinglbase{}|,         # single low-9 quotation mark
+     'ldquo'    => q|\textquotedblleft{}|,       # left double quotation mark
+     'rdquo'    => q|\textquotedblright{}|,      # right double quotation mark
+     'bdquo'    => q|\quotedblbase{}|,           # double low-9 quotation mark
+     'dagger'   => q|\textdagger{}|,             # dagger
+     'Dagger'   => q|\textdaggerdbl{}|,          # double dagger
+     'permil'   => q|\textperthousand{}|,        # per mille sign
+     'lsaquo'   => q|\guilsinglleft{}|,          # single left-pointing angle quotation mark
+     'rsaquo'   => q|\guilsinglright{}|,         # single right-pointing angle quotation mark
+     'euro'     => q|\texteuro{}|,               # euro sign
+);
+
+=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->{_dont_modify_any_para}=0; # For =begin 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 relevant 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 arbitrary 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}
+  \usepackage[T1]{fontenc}
+  \usepackage{textcomp}
+  \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>.
+
+For some pod escapes it may be necessary to include the amsmath
+package. This is not yet added to the preamble automatically.
+
+=cut
+
+sub AddPreamble {
+   my $self = shift;
+   if (@_) {
+     $self->{AddPreamble} = shift;
+   }
+   return $self->{AddPreamble};
+}
+
+=item B<AddPostamble>
+
+Logical to control whether a standard C<latex> ending is written to the output
+file after the document has been processed.
+In its simplest form this is simply:
+
+  \end{document}
+
+but can be more complicated if a index is required.
+Can be used to set or retrieve the current value.
+
+  $add = $parser->AddPostamble();
+  $parser->AddPostamble(1);
+
+If used in conjunction with C<AddPreaamble> a full latex document will
+be written that could be immediately processed by C<latex>.
+
+=cut
+
+sub AddPostamble {
+   my $self = shift;
+   if (@_) {
+     $self->{AddPostamble} = shift;
+   }
+   return $self->{AddPostamble};
+}
+
+=item B<Head1Level>
+
+The C<latex> sectioning level that should be used to correspond to
+a pod C<=head1> directive. This can be used, for example, to turn
+a C<=head1> into a C<latex> C<subsection>. This should hold a number
+corresponding to the required position in an array containing the
+following elements:
+
+ [0] chapter
+ [1] section
+ [2] subsection
+ [3] subsubsection
+ [4] paragraph
+ [5] subparagraph
+
+Can be used to set or retrieve the current value:
+
+  $parser->Head1Level(2);
+  $sect = $parser->Head1Level;
+
+Setting this number too high can result in sections that may not be reproducible
+in the expected way. For example, setting this to 4 would imply that C<=head3>
+do not have a corresponding C<latex> section (C<=head1> would correspond to
+a C<paragraph>).
+
+A check is made to ensure that the supplied value is an integer in the
+range 0 to 5.
+
+Default is for a value of 1 (i.e. a C<section>).
+
+=cut
+
+sub Head1Level {
+   my $self = shift;
+   if (@_) {
+     my $arg = shift;
+     if ($arg =~ /^\d$/ && $arg <= $#LatexSections) {
+       $self->{Head1Level} = $arg;
+     } else {
+       carp "Head1Level supplied ($arg) must be integer in range 0 to ".$#LatexSections . "- Ignoring\n";
+     }
+   }
+   return $self->{Head1Level};
+}
+
+=item B<Label>
+
+This is the label that is prefixed to all C<latex> label and index
+entries to make them unique. In general, pods have similarly titled
+sections (NAME, DESCRIPTION etc) and a C<latex> label will be multiply
+defined if more than one pod document is to be included in a single
+C<latex> file. To overcome this, this label is prefixed to a label
+whenever a label is required (joined with an underscore) or to an
+index entry (joined by an exclamation mark which is the normal index
+separator). For example, C<\label{text}> becomes C<\label{Label_text}>.
+
+Can be used to set or retrieve the current value:
+
+  $label = $parser->Label;
+  $parser->Label($label);
+
+This label is only used if C<UniqueLabels> is true.
+Its value is set automatically from the C<NAME> field
+if C<ReplaceNAMEwithSection> is true. If this is not the case
+it must be set manually before starting the parse.
+
+Default value is C<undef>.
+
+=cut
+
+sub Label {
+   my $self = shift;
+   if (@_) {
+     $self->{Label} = shift;
+   }
+   return $self->{Label};
+}
+
+=item B<LevelNoNum>
+
+Control the point at which C<latex> section numbering is turned off.
+For example, this can be used to make sure that C<latex> sections
+are numbered but subsections are not.
+
+Can be used to set or retrieve the current value:
+
+  $lev = $parser->LevelNoNum;
+  $parser->LevelNoNum(2);
+
+The argument must be an integer between 0 and 5 and is the same as the
+number described in C<Head1Level> method description. The number has
+nothing to do with the pod heading number, only the C<latex> sectioning.
+
+Default is 2. (i.e. C<latex> subsections are written as C<subsection*>
+but sections are numbered).
+
+=cut
+
+sub LevelNoNum {
+   my $self = shift;
+   if (@_) {
+     $self->{LevelNoNum} = shift;
+   }
+   return $self->{LevelNoNum};
+}
+
+=item B<MakeIndex>
+
+Controls whether C<latex> commands for creating an index are to be inserted
+into the preamble and postamble
+
+  $makeindex = $parser->MakeIndex;
+  $parser->MakeIndex(0);
+
+Irrelevant if both C<AddPreamble> and C<AddPostamble> are false (or equivalently,
+C<UserPreamble> and C<UserPostamble> are set).
+
+Default is for an index to be created.
+
+=cut
+
+sub MakeIndex {
+   my $self = shift;
+   if (@_) {
+     $self->{MakeIndex} = shift;
+   }
+   return $self->{MakeIndex};
+}
+
+=item B<ReplaceNAMEwithSection>
+
+This controls whether the C<NAME> section in the pod is to be translated
+literally or converted to a slightly modified output where the section
+name is the pod name rather than "NAME".
+
+If true, the pod segment
+
+  =head1 NAME
+
+  pod::name - purpose
+
+  =head1 SYNOPSIS
+
+is converted to the C<latex>
+
+  \section{pod::name\label{pod_name}\index{pod::name}}
+
+  Purpose
+
+  \subsection*{SYNOPSIS\label{pod_name_SYNOPSIS}%
+               \index{pod::name!SYNOPSIS}}
+
+(dependent on the value of C<Head1Level> and C<LevelNoNum>). Note that
+subsequent C<head1> directives translate to subsections rather than
+sections and that the labels and index now include the pod name (dependent
+on the value of C<UniqueLabels>).
+
+The C<Label> is set from the pod name regardless of any current value
+of C<Label>.
+
+  $mod = $parser->ReplaceNAMEwithSection;
+  $parser->ReplaceNAMEwithSection(0);
+
+Default is to translate the pod literally.
+
+=cut
+
+sub ReplaceNAMEwithSection {
+   my $self = shift;
+   if (@_) {
+     $self->{ReplaceNAMEwithSection} = shift;
+   }
+   return $self->{ReplaceNAMEwithSection};
+}
+
+=item B<StartWithNewPage>
+
+If true, each pod translation will begin with a C<latex>
+C<\clearpage>.
+
+  $parser->StartWithNewPage(1);
+  $newpage = $parser->StartWithNewPage;
+
+Default is false.
+
+=cut
+
+sub StartWithNewPage {
+   my $self = shift;
+   if (@_) {
+     $self->{StartWithNewPage} = shift;
+   }
+   return $self->{StartWithNewPage};
+}
+
+=item B<TableOfContents>
+
+If true, a table of contents will be created.
+Irrelevant if C<AddPreamble> is false or C<UserPreamble>
+is set.
+
+  $toc = $parser->TableOfContents;
+  $parser->TableOfContents(1);
+
+Default is false.
+
+=cut
+
+sub TableOfContents {
+   my $self = shift;
+   if (@_) {
+     $self->{TableOfContents} = shift;
+   }
+   return $self->{TableOfContents};
+}
+
+=item B<UniqueLabels>
+
+If true, the translator will attempt to make sure that
+each C<latex> label or index entry will be uniquely identified
+by prefixing the contents of C<Label>. This allows
+multiple documents to be combined without clashing 
+common labels such as C<DESCRIPTION> and C<SYNOPSIS>
+
+  $parser->UniqueLabels(1);
+  $unq = $parser->UniqueLabels;
+
+Default is true.
+
+=cut
+
+sub UniqueLabels {
+   my $self = shift;
+   if (@_) {
+     $self->{UniqueLabels} = shift;
+   }
+   return $self->{UniqueLabels};
+}
+
+=item B<UserPreamble>
+
+User supplied C<latex> preamble. Added before the pod translation
+data. 
+
+If set, the contents will be prepended to the output file before the translated 
+data regardless of the value of C<AddPreamble>.
+C<MakeIndex> and C<TableOfContents> will also be ignored.
+
+=cut
+
+sub UserPreamble {
+   my $self = shift;
+   if (@_) {
+     $self->{UserPreamble} = shift;
+   }
+   return $self->{UserPreamble};
+}
+
+=item B<UserPostamble>
+
+User supplied C<latex> postamble. Added after the pod translation
+data. 
+
+If set, the contents will be prepended to the output file after the translated 
+data regardless of the value of C<AddPostamble>.
+C<MakeIndex> will also be ignored.
+
+=cut
+
+sub UserPostamble {
+   my $self = shift;
+   if (@_) {
+     $self->{UserPostamble} = shift;
+   }
+   return $self->{UserPostamble};
+}
+
+=begin __PRIVATE__
+
+=item B<Lists>
+
+Contains details of the currently active lists.
+  The array contains C<Pod::List> objects. A new C<Pod::List>
+object is created each time a list is encountered and it is
+pushed onto this stack. When the list context ends, it 
+is popped from the stack. The array will be empty if no
+lists are active.
+
+Returns array of list information in list context
+Returns array ref in scalar context
+
+=cut
+
+
+
+sub lists {
+  my $self = shift;
+  return @{ $self->{_Lists} } if wantarray();
+  return $self->{_Lists};
+}
+
+=end __PRIVATE__
+
+=back
+
+=begin __PRIVATE__
+
+=head2 Subclassed methods
+
+The following methods override methods provided in the C<Pod::Select>
+base class. See C<Pod::Parser> and C<Pod::Select> for more information
+on what these methods require.
+
+=over 4
+
+=cut
+
+######### END ACCESSORS ###################
+
+# Opening pod
+
+=item B<begin_pod>
+
+Writes the C<latex> preamble if requested. Only writes something
+if AddPreamble is true. Writes a standard header unless a UserPreamble
+is defined.
+
+=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 ($self->AddPreamble) {
+
+    if (defined $self->UserPreamble) {
+
+      $preamble = $self->UserPreamble;
+
+      # Add the description of where this came from
+      $preamble .=  "\n$comment\n%%  Preamble supplied by user.\n\n";
+
+    } else {
+
+      # 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", at makeidx) . "\n";
+
+      # Table of contents
+      my $tableofcontents = '\tableofcontents';
+
+      $tableofcontents = '%% ' . $tableofcontents
+	unless $self->TableOfContents;
+
+      # Roll our own
+      $preamble = << "__TEX_HEADER__";
+\\documentclass{article}
+\\usepackage[T1]{fontenc}
+\\usepackage{textcomp}
+
+$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. Only writes something if AddPostamble
+is true. Writes a standard header unless a UserPostamble is defined.
+
+=cut
+
+sub end_pod {
+  my $self = shift;
+
+  # End string
+  my $end = '';
+
+  # Use the user version of the postamble if defined
+  if ($self->AddPostamble) {
+
+    if (defined $self->UserPostamble) {
+      $end = $self->UserPostamble;
+
+    } else {
+
+      # 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';
+
+  # Store a copy of the raw text in case we are in a =for
+  # block and need to preserve the existing latex
+  my $rawpara = $paragraph;
+
+  # Do the latex escapes
+  $paragraph = $self->_replace_special_chars($paragraph);
+
+  # Interpolate pod sequences in paragraph
+  $paragraph = $self->interpolate($paragraph, $line_num);
+  $paragraph =~ s/\s+$//;
+
+  # Replace characters that can only be done after 
+  # interpolation of interior sequences
+  $paragraph = $self->_replace_special_chars_late($paragraph);
+
+  # 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 explicitly intended for latex
+      $self->{_suppress_all_para} = 1;
+    }
+
+  } elsif ($command eq 'for') {
+
+    # =for latex
+    #   some latex
+
+    # With =for we will get the text for the full paragraph
+    # as well as the format name.
+    # We do not get an additional paragraph later on. The next
+    # paragraph is not governed by the =for
+
+    # The first line contains the format and the rest is the
+    # raw code.
+    my ($format, $chunk) = split(/\n/, $rawpara, 2);
+
+    # If we have got some latex code print it out immediately
+    # unmodified. Else do nothing.
+    if ($format =~ /^latex/i) {
+      # Make sure that next paragraph is not modfied before printing
+      $self->_output( $chunk );
+
+    }
+
+  } 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 =begin block
+  if ($self->{_dont_modify_any_para}) {
+    # Just print as is
+    $self->_output($paragraph);
+
+  } else {
+
+    return if $paragraph =~ /^\s+$/;
+
+    # Clean trailing space
+    $paragraph =~ s/\s+$//;
+
+    # Clean tabs. Routine taken from Tabs.pm
+    # by David Muir Sharnoff muir at idiom.com,
+    # slightly modified by hsmyers at sdragons.com 10/22/01
+    my @l = split("\n",$paragraph);
+    foreach (@l) {
+      1 while s/(^|\n)([^\t\n]*)(\t+)/
+	$1. $2 . (" " x 
+		  (8 * length($3)
+		   - (length($2) % 8)))
+	  /sex;
+    }
+    $paragraph = join("\n", at l);
+    # End of change.
+
+
+
+    $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 =begin block
+  if ($self->{_dont_modify_any_para}) {
+    # Just print as is
+    $self->_output($paragraph);
+
+    return;
+  }
+
+
+  # Escape latex special characters
+  $paragraph = $self->_replace_special_chars($paragraph);
+
+  # Interpolate interior sequences
+  my $expansion = $self->interpolate($paragraph, $line_num);
+  $expansion =~ s/\s+$//;
+
+  # Escape special characters that can not be done earlier
+  $expansion = $self->_replace_special_chars_late($expansion);
+
+  # 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 / - but not sure if I want to do this
+    # any more.
+    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}";
+
+  } 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;
+
+  # Don't 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 whatever
+  # simply return immediately
+  return if $self->{_suppress_all_para};
+
+  # Check to see whether we are starting a new lists
+  if (scalar($self->lists->[-1]->item) == 0) {
+
+    # Examine the paragraph to determine what type of list
+    # we have
+    $paragraph =~ s/\s+$//;
+    $paragraph =~ s/^\s+//;
+
+    my $type;
+    if (substr($paragraph, 0,1) eq '*') {
+      $type = 'itemize';
+    } elsif ($paragraph =~ /^\d/) {
+      $type = 'enumerate';
+    } else {
+      $type = 'description';
+    }
+    $self->lists->[-1]->type($type);
+
+    $self->_output("\\begin{$type}\n");
+
+  }
+
+  my $type = $self->lists->[-1]->type;
+
+  if ($type eq 'description') {
+    # Handle long items - long items do not wrap
+    # If the string is longer than 40 characters we split
+    # it into a real item header and some bold text.
+    my $maxlen = 40;
+    my ($hunk1, $hunk2) = $self->_split_delimited( $paragraph, $maxlen );
+
+    # Print the first hunk
+    $self->_output("\n\\item[{$hunk1}] ");
+
+    # and the second hunk if it is defined
+    if ($hunk2) {
+      $self->_output("\\textbf{$hunk2}");
+    } else {
+      # Not there so make sure we have a new line
+      $self->_output("\\mbox{}");
+    }
+
+  } else {
+    # If the item was '* Something' or '\d+ something' we still need to write
+    # out the something. Also allow 1) and 1.
+    my $extra_info = $paragraph;
+    $extra_info =~ s/^(\*|\d+[\.\)]?)\s*//;
+    $self->_output("\n\\item $extra_info");
+  }
+
+  # Store the item name in the object. Required so that 
+  # we can tell if the list is new or not
+  $self->lists->[-1]->item($paragraph);
+
+}
+
+=back
+
+=head2 Methods for headings
+
+=over 4
+
+=item B<head>
+
+Print a heading of the required level.
+
+  $parser->head($level, $paragraph, $parobj);
+
+The first argument is the pod heading level. The second argument
+is the contents of the heading. The 3rd argument is a Pod::Paragraph
+object so that the line number can be extracted.
+
+=cut
+
+sub head {
+  my $self = shift;
+  my $num = shift;
+  my $paragraph = shift;
+  my $parobj = shift;
+
+  # If we are replace 'head1 NAME' with a section
+  # we return immediately if we get it
+  return 
+    if ($self->{_CURRENT_HEAD1} =~ /^NAME/i && $self->ReplaceNAMEwithSection());
+
+  # Create a label
+  my $label = $self->_create_label($paragraph);
+
+  # Create an index entry
+  my $index = $self->_create_index($paragraph);
+
+  # Work out position in the above array taking into account
+  # that =head1 is equivalent to $self->Head1Level
+
+  my $level = $self->Head1Level() - 1 + $num;
+
+  # Warn if heading to large
+  if ($num > $#LatexSections) {
+    my $line = $parobj->file_line;
+    my $file = $self->input_file;
+    warn "Heading level too large ($level) for LaTeX at line $line of file $file\n";
+    $level = $#LatexSections;
+  }
+
+  # Check to see whether section should be unnumbered
+  my $star = ($level >= $self->LevelNoNum ? '*' : '');
+
+  # Section
+  $self->_output("\\" .$LatexSections[$level] .$star ."{$paragraph\\label{".$label ."}\\index{".$index."}}\n");
+
+}
+
+
+=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 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};
+
+}
+
+
+=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. It must be called before interpolation of interior
+sequences so that curly brackets and special latex characters inserted
+during interpolation are not themselves escaped. This means that < and
+> can not be modified here since the text still contains interior
+sequences.
+
+Special characters and the C<latex> equivalents are:
+
+  }     \}
+  {     \{
+  _     \_
+  $     \$
+  %     \%
+  &     \&
+  \     $\backslash$
+  ^     \^{}
+  ~     \~{}
+  #     \#
+
+=cut
+
+sub _replace_special_chars {
+  my $self = shift;
+  my $paragraph = shift;
+
+  # Replace a \ with $\backslash$
+  # This is made more complicated because the dollars will be escaped
+  # by the subsequent replacement. Easiest to add \backslash 
+  # now and then add the dollars
+  $paragraph =~ s/\\/\\backslash/g;
+
+  # Must be done after escape of \ since this command adds latex escapes
+  # Replace characters that can be escaped
+  $paragraph =~ s/([\$\#&%_{}])/\\$1/g;
+
+  # Replace ^ characters with \^{} so that $^F works okay
+  $paragraph =~ s/(\^)/\\$1\{\}/g;
+
+  # Replace tilde (~) with \texttt{\~{}}
+  $paragraph =~ s/~/\\texttt\{\\~\{\}\}/g;
+
+  # Now add the dollars around each \backslash
+  $paragraph =~ s/(\\backslash)/\$$1\$/g;
+
+  # Convert ------ to -{}-{}-{}-{}-{}-
+  $paragraph =~ s/-(?=-)/-{}/g;
+
+  return $paragraph;
+}
+
+=item B<_replace_special_chars_late>
+
+Replace special characters that can not be replaced before interior
+sequence interpolation. See C<_replace_special_chars> for a routine
+to replace special characters prior to interpolation of interior
+sequences.
+
+Does the following transformation:
+
+  <   $<$
+  >   $>$
+  |   $|$
+
+
+=cut
+
+sub _replace_special_chars_late {
+  my $self = shift;
+  my $paragraph = shift;
+
+  # < and >
+  $paragraph =~ s/(<|>)/\$$1\$/g;
+
+  # Replace | with $|$
+  $paragraph =~ s'\|'$|$'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
+}
+
+=item B<_split_delimited>
+
+Split the supplied string into two parts at approximately the
+specified word boundary. Special care is made to make sure that it
+does not split in the middle of some curly brackets.
+
+e.g. "this text is \textbf{very bold}" would not be split into
+"this text is \textbf{very" and " bold".
+
+  ($hunk1, $hunk2) = $self->_split_delimited( $para, $length);
+
+The length indicates the maximum length of hunk1.
+
+=cut
+
+# initially Supplied by hsmyers at sdragons.com
+# 10/25/01, utility to split \hbox
+# busting lines. Reformatted by TimJ to match module style.
+sub _split_delimited {
+  my $self = shift;
+  my $input = shift;
+  my $limit = shift;
+
+  # Return immediately if already small
+  return ($input, '') if length($input) < $limit;
+
+  my @output;
+  my $s = '';
+  my $t = '';
+  my $depth = 0;
+  my $token;
+
+  $input =~ s/\n/ /gm;
+  $input .= ' ';
+  foreach ( split ( //, $input ) ) {
+    $token .= $_;
+    if (/\{/) {
+      $depth++;
+    } elsif ( /}/ ) {
+      $depth--;
+    } elsif ( / / and $depth == 0) {
+      push @output, $token if ( $token and $token ne ' ' );
+      $token = '';
+    }
+  }
+
+  foreach  (@output) {
+    if (length($s) < $limit) {
+      $s .= $_;
+    } else {
+      $t .= $_;
+    }
+  }
+
+  # Tidy up
+  $s =~ s/\s+$//;
+  $t =~ s/\s+$//;
+  return ($s,$t);
+}
+
+=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>, L<Pod::Simple>.
+
+=head1 AUTHORS
+
+Tim Jenness E<lt>tjenness at cpan.orgE<gt>
+
+Bug fixes and improvements have been received from: Simon Cozens
+E<lt>simon at cozens.netE<gt>, Mark A. Hershberger
+E<lt>mah at everybody.orgE<gt>, Marcel Grunauer
+E<lt>marcel at codewerk.comE<gt>, Hugh S Myers
+E<lt>hsmyers at sdragons.comE<gt>, Peter J Acklam
+E<lt>jacklam at math.uio.noE<gt>, Sudhi Herle E<lt>sudhi at herle.netE<gt>,
+Ariel Scolnicov E<lt>ariels at compugen.co.ilE<gt>,
+Adriano Rodrigues Ferreira E<lt>ferreira at triang.com.brE<gt>,
+R. de Vries E<lt>r.de.vries at dutchspace.nlE<gt> and
+Dave Mitchell E<lt>davem at iabyn.comE<gt>.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011 Tim Jenness.
+Copyright (C) 2000-2004 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$
+
+=end __PRIVATE__
+
+=cut
+
+1;



View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/-/compare/ba3aa87711921cb3cf0ad3d0d8d9e8f36108c7da...01f3672e3b08bbbceecbb19be33f56404e15f92c

-- 
View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/-/compare/ba3aa87711921cb3cf0ad3d0d8d9e8f36108c7da...01f3672e3b08bbbceecbb19be33f56404e15f92c
You're receiving this email because of your account on xgitlab.cels.anl.gov.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/darshan-commits/attachments/20200902/de5d1490/attachment-0001.html>


More information about the Darshan-commits mailing list