#!/usr/bin/perl
eval 'exec perl -S $0 ${1+"$@"}'
       if $running_under_some_shell;

=head1 NAME

pod2fm - convert pod format to FrameMaker documents and book file

=head1 SYNOPSIS

   pod2fm [-mmlonly |
           -nodoc [-lock]
           [-book [I<book_name>] [-noopen]
               [-template I<document> [-format I<types>]... [-toc] [-index]
           ]
       ]

=head1 DESCRIPTION

This program parses all files with .pod extension and creates FrameMaker
documents. You can control what is generated by arguments given on the
command line. I<Pod2fm> can:

=item * Generate Frame MML, MIF, and binary formats.

=item * Generate hypertext links to a group of documents.

=item * Create a Frame 'book' that includes all of the documents from a run.

=item * Create Table of Contents and Index documents.

=item * Create documents that can be used with FrameViewer for On-Line Docs.

=head1 OPTIONS

=over 12

=item B<-mmlonly>

=item B<-nommlonly>

This switch tells I<pod2fm> if it should stop execution after it has generated
the 'MML' version of the document. The document is written into a file with the
'.mml' extension.

If B<-mmlonly> is specified, it can be the only command line switch.

The default is 'B<-nommlonly>'.

=item B<-nodoc>

=item B<-doc>

The switch instructs I<pod2fm> to use the FrameMaker tool 'fmbatch' to convert
the '.doc' file, which is in MIF format, in to the binary FrameMaker format.

The default is B<-doc>.

=item B<-lock>

=item B<-nolock>

I<Pod2fm> generates Hypertext Marker that allow you to click on a marked word in
a document and Frame will take you to the spot in a document that the marker
is pointing too. To be able to use this feature, you need to save the
documents as 'locked' or 'read only'. The B<-lock> option will cause I<pod2fm>
to generate 'locked' versions of the documents.

The B<-lock> option only works if you are generating binary documents. (See
the B<-doc> option.)

The default is B<-nolock>.

=item B<-book> [I<book_name>]

This switch allows I<pod2fm> to create a FrameMaker book file that contains
all of the documents that are on the command line. A book is a way to
organize a group of related documents so they can operated on at the same
time.  A book file allow you to apply a common format to all the documents, and
print all of them at the same time.

I<book_name> is an optional argument to -book. It allows you to specify a name
for the book file. If I<book_name> is not specified, it defaults to 'perl'.
In any case, the file name extension is '.book'.

=item B<-noopen>

=item B<-open>

If this option is on the command line, I<pod2mf> will try to open the book it
created in FrameMaker. Because this options works on the book file, you must be
generating a book with the B<-book> option.

The default is B<-open>.

=item B<-template> I<document>

I<Pod2fm> generates a minimal format for the documents it produces. You can
use the B<-template> option to specify a template document that I<pod2fm> can
copy the format from so that you can control the format. You can control which
format in the template document to use with the B<-format> option. The
I<document> name is required argument to B<-template>, and specifies path to
the document template.

=item B<-format> I<type>

The option B<-format> allows you to control which format to copy from the
template document specified with the B<-template> option. You can specify one
or more arguments to each B<-format> option by giving a comma separated list
of format types, like this:

   -format Page,Paragraph,Character

You can also have more than one B<-format> option on the command line.

The legal format I<type>s are:

   all         All type are specified (Default).
   Character   Character Formats.
   Paragraph   Paragraph Formats.
   Page        Master Page Layouts.
   Reference   Reference Page Layouts.
   Table       Table Formats.
   Variables   Variable Definitions.
   Math        Math Definitions.
   Cross       Cross-Reference Definitions.
   Color       Color Definitions.
   Conditional Conditional Text Definitions.

There are two other I<type>s that can be included as an argument to control
how the other I<types> are used:

   Break       Preserve Page Breaks
   Other       Preserve Other Format Changes.

=item B<-toc>

=item B<-notoc>

=item B<-index>

=item B<-noindex>

When you are generating a book from a template with I<pod2fm>, you can generate
a Table of Contents and an Index by specifying the B<-toc> and the B<-index>
options. See the I<Table of Contents> and I<Index> sub-sections of the
B<TEMPLATES> section of this man page, for more information.

The defaults are B<-notoc> and B<-noindex>.

=back

=head1 TEMPLATES

By using the B<-template> command line option, when you are generating a book
using the B<-book> option, you can override the default formats that I<pod2fm>
produces.

A template is a FrameMaker document, the binary form or MIF, that has formats
you want already applied to it. With this version of I<pod2fm>, you can
override the Master Page and Reference Page layouts, and Paragraph formats.
There are other formats that you can specify, like Character formats and Color
definitions, but this version of I<pod2fm> does not do anything with them.

=head2 Paragraph Formats

There are several Paragraph Formats that I<pod2fm> uses and there is a mapping
from the pod command to the paragraph format that is produced. The exception
to the mapping is the I<=over> and I<=back> commands: they modify the paragraph
format by shifting its left edge by .1" times the amount in the I<=over> command.
You need to take this into account when you are changing the paragraph format.
If you drop the size of the font in the format, you do not get a smaller amount
of shifting. An I<=over> 5 always give an indent of .5".

The paragraph formats that I<pod2fm> uses are:

=over 12

=item B<pod_TITLE>

Paragraphs marked with this format contain the name of the pod. The name is
automatically added to the start of each document, and this format is only
used here.

You can use the B<pod_TITLE> tag to generate a header or footer with the name of
the pod in it by changing the Master Page layout. If you are generating a book,
this format is exported so that you can create a Table of Contents by changing
the Reference Page.

=item B<pod_Body>

This format marks a standard paragraph. The left edge moves with
each I<=over> I<n> and I<=back>. The edge moves by I<n>*.1".

=item B<pod_head1>

This format is used for section headers. The command is used like:

   =head1 I<text>

where I<text> is printed in this format. The I<=over> or I<=back> command do not
change this format.

If you are generating a book, this format is exported so that you can create a
Table of Contents by changing the Reference Page. Also, a Marker is placed on
the I<text> so that it can be placed in an Index.

=item B<pod_head2>

This format is used for sub-section headers. The command is used like:

   =head2 I<text>

where I<text> is printed in this format. The I<=over> or I<=back> command do not
change this format.

If you are generating a book, this format is exported so that you can create a
Table of Contents by changing the Reference Page. Also, a Marker is placed on
the I<text> so that it can be placed in an Index.

=item B<pod_ol>

This format is used on ordered (numbered) lists. If the indent command is in
this form:

   =item I<n>[I<.>]

where I<n> is any number followed by an optional period. The next paragraph
will be marked with this format and will print as a hanging indent that starts
with an automatically generated number and a period. The start of the
paragraph is shifted by the amount in the I<=over> command. Any paragraphs that
come after the first are marked with B<pod_Body> and the left edge is shifted
by the amount from the I<=over> command.

=item B<pod_ul>

This format is used on unordered lists. If the indent command is in this form:

   =item *

the next paragraph will be marked with this format and will print as a
hanging indent that starts bullet. The start of the paragraph is shifted by
the amount in the I<=over> command. Any paragraphs that come after the first
are marked with B<pod_Body> and the left edge is shifted by the amount from
the I<=over> command.

=item B<pod_dl>

This format is used on description lists. If the indent command is in this form:

   =item * I<text>

the I<text> will be printed after a bullet, on a line by itself.  Any
paragraphs that come after the first are marked with B<pod_Body> and the left
edge is shifted by the amount from the I<=over> command.

=item B<pod_hi>

This format is used on hanging indent lists. If the indent command is in
this form:

   =item I<text>

the I<text> will be printed as a hanging indent. The next paragraph will be
marked with this format and will print with the start of the paragraph shifted
by the amount in the I<=over> command.  Any paragraphs that come after the first
are marked with B<pod_Body> and the left edge is shifted by the amount from
the I<=over> command.

=item B<pod_il>

This format is used on implied lists. If the first line of a paragraph is
in this form:

   ____I<hang>_______I<text>
    |          |
    +- spaces  +- tabs
         or
        tabs

the I<hang> will be printed as a hanging indent and the I<text> will be printed
with the left edge shifted to 2.5" from the current B<pod_Body> left edge.  The
rest of the lines in the paragraph are treated the same, i.e.: each line in the
pod's paragraph is converted to a FrameMaker paragraph that is marked with
B<pod_il>. Any paragraphs that come after the first are marked with
B<pod_Body> and the left edge is shifted by the amount from the I<=over>
command.

=item B<pod_pre>

This format is used on verbatim paragraphs. If the first line of a
paragraph is in this form:

   ____I<text>
    |
    +- spaces
         or
        tabs

the I<text>, including the leading white space,  will be printed with the
left edge shifted to the current B<pod_Body> left edge.  The rest of the lines
in the paragraph are treated the same, i.e.: each line in the pod's paragraph is
converted to a FrameMaker paragraph that is marked with B<pod_pre>. Any
paragraphs that come after the first are marked with B<pod_Body> and the left
edge is shifted by the amount from the I<=over> command.

=back

=head2 Table of Contents

If you are producing a book, and you have a B<-template> command line option
and you are importing the Master Page Layout (B<-format Page> or the default),
you can produce a Table of Contents by adding the B<-toc> option. I<Pod2fm>
will automatically add a generated document called I<book_name>TOC.doc to
the book file, where I<book_name> is the optional argument to the B<-book>
command line option. If no argument is give on the B<-book>, you will get a
document called perlTOC.doc.

To specify the format of the Table of Contents, you need to go to the reference
pages of the template document and create a flow called 'TOC'. Within the flow,
you need to create a picture of what the Table of Contents will look like.
You can add I<Building block> to the picture that allows you to control what
is printed, things like the page number and text for the TOC entry. See the
FrameMaker On-Line Help or I<Using FrameMaker> printed manual for a complete
description of how to set up a TOC Reference page.

The TOC entry is derived from paragraphs in the documents in the book that are
marked with specific paragraph formats. I<Pod2fm> uses the paragraph formats
B<pod_TITLE>, B<pod_head1>, and B<pod_head2> to mark the TOC entries.

To make a TOC entry show, you need to create a new paragraph format that tracks
the format used in the documents. The new paragraph have the form:

   I<format_name>TOC

where I<format_name> is the format name used in the document. Here is an
example of TOC specification:

   Paragraph tagged    Specifies
   ----------------    ---------
   pod_TITLE           <$paratext><$nopage>
   pod_head1               <$paratext>\t<$pagenum>
   pod_head2                   <$paratext>\t<$pagenum>

would print something like this:

   POD2FM
       NAME                                    1
       SYNOPSIS                                1
       DESCRIPTION                             1
       OPTIONS                                 1
       TEMPLATES                               3
           Paragraph Formats                   3
           Table of Contents                   5
           Index                               6
       BUGS                                    6
       AUTHORS                                 7

=head2 Index

An Index document is much the same as a Table of Contents document: you must
be generating a book and importing Reference Page Layouts from a template,
and have a B<-index> command line option.

The format for the Index is also specified on a Reference Page in a flow called
B<IX>, and it has it's own set of I<Building Blocks>. Please see the FrameMaker
documentation for more details on how to create the Index Reference Page.

I<Pod2fm> generates the index from any I<Index> markers that have been place
in the documents. The markers are generated on any I<=head> or I<=item> command,
and any interior sequences (like I\<\>, B\<\>, and L\<\>) that refers to
and I<=head> or I<=item>.

=head1 BUGS

I<Fmbatch> dies when it tries to work on a Table of Contents or an Index.
This happens when both in the ImportFormats and the Update. To get around this,
just open the book file in I<maker> and do the Import Formats and Update there.

You can't change the amount of indent using a template file (yet...).

=head1 AUTHORS

Based on pod2html. Extended for MML by
Mark Pease <[email protected]>.
fmbatch and book support added by Tim Bunce <[email protected]>.

Please send bug reports to Mark Pease <[email protected]>.

=cut

use Getopt::Long;

# To do:
#       add documentation

*RS = */;
*ERRNO = *!;
$| = 1;

################################################################################
# COMMAND LINE ACTIONS
#
#   Set up defaults for the command line, and process it.
################################################################################

$do_mmlonly = 0;                # Produce MIF ".doc" files
$do_doc = 1;                    # Generate the binary ".doc" files
$save_type = 'd';               # SaveAs type: "d" - normal format, "l" - locked
$do_book = 0;                   # Don't Generate a book
$book_name = 'perl';            # The default name for a book.
$import_formats = 'pflcvrtxkmBO';# Default formats to import from Template
$do_toc = 0;                    # Don't include a TOC
$do_index = 0;                  # Don't include a INDEX
$open_frame = 1;                # Open maker on the book file once it is built

GetOptions("debug=s@", "mmlonly!", "doc!", "book:s", "lock!", "template=s", "format=s@", "toc!", "index!", "open!")
   || die "$0: Unable to process command line.\n";

#
# Verify options
#
if (defined $opt_mmlonly and $opt_mmlonly) {
   #
   # Generate MML only.
   #
   $do_mmlonly = 1;
   $do_doc = 0;
   $do_book = 0;
   $do_toc = 0;
   $do_index = 0;
   $open_frame = 0;

   warn "$0: You can't produce .${doc_ext} files because you asked for MML only.
   Continuing, only producing .mml\n"
       if $opt_doc;

   warn "$0: You can't generate a book because you asked for MML only.
   Continuing, only producing .mml\n"
       if $opt_book or $opt_lock or $opt_toc or $opt_index;

   warn "$0: You can't import formats because you asked for MML only.
   Continuing, only producing .mml\n"
       if defined $opt_template or defined @opt_formats;

} else {
   #
   # Generate MIF, and maybe other stuff.
   #
   $do_mmlonly = 0;

   #
   # Process Document Generation options.
   #
   $do_doc = $opt_doc if defined $opt_doc;

   #
   # Process book options.
   #
   if (defined $opt_book or $do_book) {
       #
       # Generate a MIF file for the book, with the default name of "perl".
       #
       $do_book = 1;
       $opt_book = $book_name unless $opt_book;
       $batch_name = $opt_book;

       #
       # Process lock options.
       #
       $save_type = (defined $opt_lock and $opt_lock) ? 'l' : 'd';

       #
       # Check for templates and formats.
       #
       die "$0: Template file $opt_template does not exist!\n"
           if defined($opt_template) and !(-e $opt_template);

       die "$0: You must specify a template using -template <file>."
           if defined(@opt_format) and !defined($opt_template);

       #
       # Process the format options.
       #
       if (defined(@opt_format)) {
           my %type;

   FORMAT: foreach (@opt_format) {
               #
               # Each format argument could be a "," seperated list.
               #
               foreach (split /,/) {
                   {
                       # Do it all
                       /all/i  and do {$type{$_}='pflcvrtxkmBO',last FORMAT;};

                       # Presere Page Breaks
                       /^b/i   and do {$type{$_}='m',last;};

                       # Character Formats
                       /^ch/i  and do {$type{$_}='f',last;};

                       # Color Definitions
                       /^col/i and do {$type{$_}='k',last;};

                       # Conditional Text
                       /^con/i and do {$type{$_}='x',last;};

                       # Cross-references
                       /^cr/i  and do {$type{$_}='c',last;};

                       # Math Definitions
                       /^m/i   and do {$type{$_}='m',last;};

                       # Presere Other Formats
                       /^o/i   and do {$type{$_}='m',last;};

                       # Master Page Layouts
                       /^pag/i and do {$type{$_}='l',last;};

                       # Paragraph Formats
                       /^par/i and do {$type{$_}='p',last;};

                       # References Pages
                       /^r/i   and do {$type{$_}='r',last;};

                       # Table Formats
                       /^t/i   and do {$type{$_}='t',last;};

                       # Varables
                       /^v/i   and do {$type{$_}='v',last;};

                       # Default
                       die "$0: Unknow format type $_\n";
                   }
               }
           }
           $import_formats = '';           # Start with nothing.
           foreach (keys %format) {
               $import_formats .= $format{$_};
           }
       }

       #
       # Make sure we can do TOC and INDEX's
       #
       if (defined $opt_toc and $opt_toc ) {
           if (!$opt_template or !$import_formats =~ /r/) {
               warn "$0: You can't generate a Table of Contents unless you " .
               "specify a template and you ask for Page formats to be " .
               "imported.\n" .
               "Continuing with out generating a TOC.\n";
               $do_toc = 0;
           } else {
               $do_toc = 1;
           }
       }

       if (defined $opt_index and $opt_index) {
           if (!$opt_template and !$import_formats =~ /r/) {
               warn "$0: You can't generate an Index unless you specify a " .
               "template and you ask for Page formats to be imported.\n" .
               "Continuing with out generating an INDEX.\n";
               $do_index = 0;
           } else {
               $do_index = 1;
           }
       }
   } else {
       #
       # We are not working with a book.
       #
       $batch_name = "batch";
       $do_book = 0;
       $do_toc = 0;
       $do_index = 0;
       $open_frame = 0;
   }
}

#
# check for podnames on command line
#
while ($ARGV[0]) {
   push(@Pods,shift);
}

################################################################################
# CONFIGURE
#
#
################################################################################

$book_ext = 'book';
$doc_ext = 'doc';
$fmbatch = 'fmbatch';
$fmbatch = 'fmbatch -i' if $ENV{FM_PROGNAME} && $ENV{FM_PROGNAME} =~ m/^i/;

#
# Page formats
#
$TopMargin = .75;
$BottomMargin = .75;
$LeftMargin = .75;
$RightMargin = .75;

#
# Paragraph indents and tab stop locations in inches.
#
$IndentAmount = 0.1;

$BodyLeft = 0.3;
$BodyIndent = 0.3;

@ListTab = ($BodyLeft, $BodyLeft + 1, $BodyLeft + 2);

$ilLeft = $BodyLeft + 2.0;
$ilIndent = $BodyLeft + 0.5;
@ilTab = ($ilLeft, $ilLeft + 1, $ilLeft + 2);

$dlLeft = $BodyLeft;
$dlIndent = $BodyLeft;

# Create "Safe" '<' and '>' for use in hypertext markers.

${gt} = noremap(">");
${lt} = noremap("<");

$dir=".";           # location of pods

# look in these pods for things not found within the current pod
# be careful tho, namespace collisions cause stupid links

@inclusions = qw[
    perlfunc perlvar perlrun perlop
];

################################################################################
# END CONFIGURE
################################################################################

$A={};  # The beginning of all things

unless(@Pods){
   opendir(DIR,$dir)  or  die "Can't opendir $dir: $ERRNO";
   @Pods = grep(/\.pod$/,readdir(DIR));
   closedir(DIR) or die "Can't closedir $dir: $ERRNO";
}
@Pods or die "expected pods";

my @book;       # Build a FrameMaker book file for all the parts
my @fmbatch;    # Build an fmbatch script for mif-doc conversion

if ($do_book or $do_doc) {
   if ($do_book) {
       push @book, "<Book 3.00>";
       push @book, "<BWindowRect 5 26 301 870>";
       if ($do_toc) {
           push @book, "<BookComponent";
           push @book, " <FileName `<c\\>${opt_book}TOC.${doc_ext}'>";
           push @book, " <PageNumPrefix `'>";
           push @book, " <PageNumSuffix `'>";
           push @book, " <FileNameSuffix `TOC'>";
           push @book, " <DeriveType TOC>";
           foreach(qw(pod_TITLE pod_head1 pod_head2)) {
               push @book, " <DeriveTag `$_'>";
           }
           push @book, " <DefaultPrint Yes>";
           push @book, " <DefaultApply No>";
           push @book, " <DefaultDerive Yes>";
           push @book, " <DeriveLinks Yes>";
           push @book, ">";
       }
   }
   foreach $podfh ( @Pods ) {
       warn "$0: '$podfh' is not a file: $!" unless -f $podfh;
       ($pod = $podfh) =~ s/\.pod$//;
       if ($do_doc) {
           push @fmbatch, "echo Building $pod.${doc_ext}";
           push @fmbatch, "Open $pod.${doc_ext}";
           push @fmbatch, "Validate $pod.${doc_ext}";  # test
           push @fmbatch, "SaveAs $save_type  $pod.${doc_ext} $pod.${doc_ext}";
           push @fmbatch, "Quit $pod.${doc_ext}";
       }
       if ($do_book) {
           push @book, "<BookComponent";
           push @book, " <FileName `<c\\>$pod.${doc_ext}'>";
           push @book, " <PageNumPrefix `'>";
           push @book, " <PageNumSuffix `'>";
           push @book, " <DefaultPrint Yes>";
           push @book, " <DefaultApply Yes>";
           push @book, ">";
       }
   }
   if ($do_book) {
       if ($do_index) {
           push @book, "<BookComponent";
           push @book, " <FileName `<c\\>${opt_book}IDX.${doc_ext}'>";
           push @book, " <PageNumPrefix `'>";
           push @book, " <PageNumSuffix `'>";
           push @book, " <FileNameSuffix `doc'>";
           push @book, " <DeriveType IDX>";
           foreach(qw(Index)) {
               push @book, " <DeriveTag `$_'>";
           }
           push @book, " <DefaultPrint Yes>";
           push @book, " <DefaultApply No>";
           push @book, " <DefaultDerive Yes>";
           push @book, " <DeriveLinks Yes>";
           push @book, ">";
       }
       open(BOOK,">${opt_book}.${book_ext}")
           || die "$0: Unable to open the book file ${opt_book}.${book_ext}: $!\n";
       print BOOK join("\n", @book);
       close(BOOK);
   }
}

# loop twice through the pods, first to learn the links, then to produce mml
for $count (0,1){
   (print "Scanning pods...\n") unless $count;
   foreach $podfh ( @Pods ) {
       ($pod = $podfh) =~ s/\.pod$//;
       Debug("files", "opening 2 $podfh" );
       (print "Creating $pod.${doc_ext} from $podfh\n") if $count;
       $RS = "\n=";        # grok pods by item (Nonstandard but effecient)
       open($podfh,"<".$podfh)  || die "can't open $podfh: $ERRNO";
       @all=<$podfh>;
       close($podfh);
       $RS = "\n";
       $all[0]=~s/^=//;
       for(@all){s/=$//;}
       $Podnames{$pod} = 1;
       $in_list=0;
       $mml=$pod.".${doc_ext}";
       if($count){             # give us a mml and rcs header
           open(MML, ">$pod.mml")
                       || die "can't create $mml: $ERRNO";
           print MML <<'MML__EOQ', <<"MML__EOQQ";
<MML>
<Comment \$Id\$ >
<Comment \$Log\$ >
MML__EOQ
<Comment "Paragraph Format Definition Section">
<!DefinePar pod_Body
   <LeftIndent $BodyLeft">
   <FirstIndent $BodyIndent">
   <WithNext No>
   <SpaceBefore 6pt>
   <SpaceAfter 6pt>
   <BlockSize 2>
   <pts 12>
>
<!DefinePar pod_TITLE
   <LeftIndent 0">
   <FirstIndent 0">
   <WithNext Yes>
   <SpaceBefore 12pt>
   <SpaceAfter 8pt>
   <pts 14>
   <bold>
>
<!DefinePar pod_head1
   <pts 14>
   <WithNext Yes>
   <SpaceBefore 12pt>
   <SpaceAfter 8pt>
   <bold>
>
<!DefinePar pod_head2
   <pts 14>
   <WithNext Yes>
   <SpaceBefore 12pt>
   <SpaceAfter 8pt>
   <bold>
>
<!DefinePar pod_ol
   <pts 12>
   <WithNext No>
   <SpaceBefore 6pt>
   <SpaceAfter 6pt>
   <nobold>
   <LeftIndent $BodyLeft">
   <FirstIndent $BodyLeft">
   <AutoNumber Yes>
   <NumberFormat "+.\\t">
   <TabStops
       <TabStop $ListTab[0]">
       <TabStop $ListTab[1]">
       <TabStop $ListTab[2]">
   >
>
<!DefinePar pod_ul
   <pts 12>
   <WithNext No>
   <SpaceBefore 6pt>
   <SpaceAfter 6pt>
   <nobold>
   <LeftIndent $BodyLeft">
   <FirstIndent $BodyLeft">
   <AutoNumber Yes>
   <NumberFormat "    \\xa5 \\t">
   <TabStops
       <TabStop $ListTab[0]">
       <TabStop $ListTab[1]">
       <TabStop $ListTab[2]">
   >
>
<!DefinePar pod_il
   <pts 12>
   <WithNext No>
   <SpaceBefore 3pt>
   <SpaceAfter 3pt>
   <nobold>
   <LeftIndent $ilLeft">
   <FirstIndent $ilIndent">
   <AutoNumber No>
   <TabStops
       <TabStop $ilTab[0]">
       <TabStop $ilTab[1]">
       <TabStop $ilTab[2]">
   >
>
<!DefinePar pod_dl
   <family Times>
   <pts 12>
   <WithNext No>
   <SpaceBefore 6pt>
   <SpaceAfter 6pt>
   <LeftIndent $dlLeft">
   <FirstIndent $dlIndent">
   <AutoNumber Yes>
   <NumberFormat "\\xa5  ">
>
<!DefinePar pod_hi
   <family Times>
   <pts 12>
   <WithNext No>
   <SpaceBefore 6pt>
   <SpaceAfter 6pt>
   <LeftIndent $BodyLeft">
   <FirstIndent $BodyLeft">
   <AutoNumber No>
   <TabStops
       <TabStop $BodyLeft">
   >
>
<!DefinePar pod_pre
   <family Courier>
   <pts 10>
   <AutoNumber No>
   <LeftIndent $BodyLeft">
   <FirstIndent $BodyLeft">
   <WithNext No>
   <SpaceBefore 0pt>
   <SpaceAfter 0pt>
>

<Comment "Document Layout Section">
<TopMargin $TopMargin>
<BottomMargin $BottomMargin>
<LeftMargin $LeftMargin>
<RightMargin $RightMargin>
<RightFooter "Page #">

<Comment "Document Text Section">
<pod_TITLE>
\U$pod\E
MML__EOQQ
       }

       for($i=0;$i<=$#all;$i++){       # decide what to do with each chunk
           $all[$i] =~ /^(\w+)\s*(.*)\n?([^\0]*)$/ ;
           ($cmd, $title, $rest) = ($1,$2,$3);
           if ($cmd eq "item") {
               if($count ){    # producting mml
                   (scalar(@depth)) or do_list("over","5",$all[$i],\$in_list,\@depth);
                   do_item($title,$rest,$in_list,@depth);
               }
               else{
                   # scan item
                   scan_thing("item",$title,$pod);
               }
           }
           elsif ($cmd =~ /^head([12])/){
               $num=$1;
               if($count){     # producting mml
                   do_hdr($num,$title,$rest,@depth);
               }
               else{
                   # header scan
                   scan_thing($cmd,$title,$pod); # skip head1
               }
           }
           elsif ($cmd =~ /^over/) {
               $count and do_list("over",$title,$all[$i+1],\$in_list,\@depth);
           }
           elsif ($cmd =~ /^back/) {
               if($count){     # producting mml
                   scalar(@depth) or next; # just skip it
                   do_list("back",$title,$all[$i+1],\$in_list,\@depth);
                   print_Body(@depth);
                   do_rest($title.$rest,@depth);
               }
           }
           elsif ($cmd =~ /^cut/) {
               next;
           }
           elsif ($cmd =~ /^for/){  # experimental pragma mml
               if($count){  # producing mml
                   if($title =~ s/^mml//){
                       $in_mml =1;
                       do_rest($title.$rest,@depth);
                   }
               }
           }
           elsif ($cmd =~ /^begin/){  # experimental pragma mml
               if($count){  # producing mml
                   if($title =~ s/^mml//){
                       print MML $title,"\n",$rest;
                   }
                   elsif($title =~ /^end/){
                       next;
                   }
               }
           }
           elsif($opt_debug{"misc"}){
               (warn "unrecognized header: $cmd");
           }
       }
       # close open lists without '=back' stmts
       if($count){ # producing html
           while(scalar(@depth)){
                do_list("back",$title,$all[$i+1],\$in_list,\@depth);
               print_Body(@depth);
           }

           close(MML); # must close to flush pipes etc

           #
           # Start mif converter, if we can.
           #
           unless ($do_mmlonly) {
               system("mmltomif $pod.mml $mml");
               warn "$0: Unable to run mmltomif on $pod.mml\n" if $? >> 8;
           }
       }
   }
}

if ($do_doc) {
   if ($do_book) {
       push @fmbatch,
           "echo Components complete, updating ${opt_book}.${book_ext}...";
       push @fmbatch, "Open ${opt_book}.${book_ext}";
       #push @fmbatch, "Validate ${opt_book}.${book_ext}";     # test
       if ($opt_template) {
           # hack to avoid locks :-)
           # system("cp $opt_template x.${doc_ext}");
           # $opt_template = 'x.${doc_ext}';
           push @fmbatch,"Open $opt_template";
           push @fmbatch,
               "ImportFormats $import_formats ${opt_book}.${book_ext} $opt_template";
           push @fmbatch,"Quit $opt_template";
       }
       push @fmbatch, "Update ${opt_book}.${book_ext}";        # Now Update
       push @fmbatch, "SaveAs $save_type ${opt_book}.${book_ext} ${opt_book}.${book_ext}";
       push @fmbatch, "Quit ${opt_book}.${book_ext}";
   }

   open(BATCH, ">${batch_name}.fmbatch")
       || die "$0: Unable to create ${opt_book}.fmbatch\n";
   print BATCH join("\n", @fmbatch);
   close(BATCH);

   system("$fmbatch ${batch_name}.fmbatch");
   die "$0: Unable to run $fmbatch on ${opt_book}.fmbatch\n" if $? >> 8;
}

system("fmclient -f ${opt_book}.${book_ext}") if $open_frame;

exit 0;

################################################################################
#
# Subroutine: print_Body
#
# Description:
#   This routine handles the formating of Body paragraphs.
#
################################################################################

sub print_Body {
   my(@depth) = @_;
   my $temp;

   my ($over) = get_shift(@depth);

   print MML "<pod_Body>\n";
   $temp = $BodyLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $BodyIndent + $over;
   print MML "<FirstIndent $temp\">\n";
}

################################################################################
#
# Subroutine: print_pre
#
# Description:
#   This routine handles the formating of pre (preformated) paragraphs.
#
################################################################################

sub print_pre {
   my(@depth) = @_;
   my $temp;

   my ($over) = get_shift(@depth);

   print MML "<pod_pre>\n";
   $temp = $BodyLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $BodyLeft + $over;
   print MML "<FirstIndent $temp\">\n";
}

################################################################################
#
# Subroutine: print_il
#
# Description:
#   This routine handles the formating of il (indented) lists. This is an
#   implied format.
#
################################################################################

sub print_il {
   my(@depth) = @_;
   my $temp;

   my ($over, $list) = get_shift(@depth);

   print MML   "<pod_il>\n";
   $temp = $ilLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $ilIndent + $over;
   print MML "<FirstIndent $temp\">\n";
   print MML   "<TabStops \n";
   foreach $tab (@ilTab) {
       $temp = $tab +$over;
       print MML "    <TabStop $temp\">\n";
   }
   print MML ">\n";
}

################################################################################
#
# Subroutine: print_ol
#
# Description:
#   This routine handles the formating of ol (ordered or numbered) lists.
#
################################################################################

sub print_ol {
   my(@depth) = @_;
   my $temp;

   my ($over, $list) = get_shift(@depth);

   print MML   "<pod_ol>\n";
   $temp = $BodyLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $BodyLeft + $list;
   print MML "<FirstIndent $temp\">\n";
   print MML   "<TabStops \n";
   foreach $tab (@ListTab) {
       $temp = $tab + $over;
       print MML "    <TabStop $temp\">\n";
   }
   print MML ">\n";
}

################################################################################
#
# Subroutine: print_ul
#
# Description:
#   This routine handles the formating of ul (unordered/unnumbered) lists.
#
################################################################################

sub print_ul {
   my(@depth) = @_;
   my $temp;

   my ($over, $list) = get_shift(@depth);

   print MML   "<pod_ul>\n";
   $temp = $BodyLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $BodyLeft + $list;
   print MML "<FirstIndent $temp\">\n";
   print MML   "<TabStops \n";
   foreach $tab (@ListTab) {
       $temp = $tab + $over;
       print MML "    <TabStop $temp\">\n";
   }
   print MML ">\n";
}

################################################################################
#
# Subroutine: print_dl
#
# Description:
#   This routine handles the formating of dl (description) lists.
#
################################################################################

sub print_dl {
   my(@depth) = @_;
   my $temp;

   my ($over, $list) = get_shift(@depth);

   print MML   "<pod_dl>\n";
   $temp = $dlLeft + $list;
   print MML "<LeftIndent $temp\">\n";
   $temp = $dlIndent + $list;
   print MML "<FirstIndent $temp\">\n";
}

################################################################################
#
# Subroutine: print_hi
#
# Description:
#   This routine handles the formating of hi (hanging indent) paragraphs.
#
################################################################################

sub print_hi {
   my(@depth) = @_;
   my $temp;

   my ($over, $list) = get_shift(@depth);

   print MML   "<pod_hi>\n";
   $temp = $BodyLeft + $over;
   print MML "<LeftIndent $temp\">\n";
   $temp = $BodyLeft + $list;
   print MML "<FirstIndent $temp\">\n";
   $temp = $BodyLeft + $over;
   print MML   "<TabStops \n" .
               "    <TabStop $temp\">\n".
               ">\n";
}

################################################################################
#
# Subroutine: get_shift
#
# Description:
#   This routine finds the amount of shift that needs to happen because of an
#   "over" or a "item".
#
################################################################################

sub get_shift {
   my (@depth) = @_;
   my $over = 0;
   my $list = 0;

   foreach $shift (@depth) {
       $list = $over;
       $over += $shift;
   }

   return ($over*$IndentAmount, $list*$IndentAmount);
}

################################################################################
#
# Subroutine: print_marker
#
# Description:
#   This routine outputs a hypertext marker, and, if an index is going to be
#   generated, an index marker.
#
################################################################################

sub print_marker {
   my ($type, $value, $file) = @_;
   my $marker;

   if ($type eq "NAME") {
       $marker =
       "${lt}Marker ${lt}MType 8${gt} ${lt}MText `newlink ${value}'${gt}${gt}";
       if ($do_index) {
           $value = pre_escapes($index{$value});
           $marker .=
           "${lt}Marker ${lt}MType 2${gt} ${lt}MText `${value}'${gt}${gt}";
       }
   } else {
       $marker =
       "${lt}Marker ${lt}MType 8${gt} ${lt}MText `gotolink ${file}:${value}'${gt}${gt}";
   }
   return $marker;
}

sub do_list{
   my($which,$amount,$next_one,$list_type,$depth)=@_;
   my($key);
   if($which eq "over"){
       ($key) = ($next_one =~ /^item\s+(.*)/);
       $key or warn "Bad list, $1\n" if $opt_debug{"misc"};
       if($key =~ /^\d\.?/){
           $$list_type = "OL";
       } elsif($key =~ /^\*\s*$/){
           $$list_type="UL";
       } elsif($key =~ /^\*\s*\w/){
           $$list_type="DL";
       } elsif($key =~ /^\w+/){
           $$list_type="HI";
       } else{
           (warn "unknown list type for item $key") if $opt_debug{"misc"};
       }
       push(@$depth, $amount);
   }
   elsif($which eq "back"){
       $$list_type="";
       $amount = pop(@$depth);
   }
}

sub do_hdr{
   my($num,$title,$rest,@depth)=@_;
   ($num == 1) and print MML "\n";
   process_thing(\$title,"NAME");
   print MML qq{\n<pod_head$num>\n};
   print MML "$title\n";
   print_Body(@depth);
   do_rest($rest,@depth);
}

sub do_item{
   my($title,$rest,$list_type,@depth)=@_;
   process_thing(\$title,"NAME");
   if($list_type eq "DL") {
       print_dl(@depth);
       $title =~ s/\*\s*//;
       print MML "<bold>$title<nobold>\n";
       print_Body(@depth);
   } elsif ($list_type eq "OL") {
       print_ol(@depth);
   } elsif ($list_type eq "UL") {
       print_ul(@depth);
   } else {
       print_hi(@depth);
       my $over = (get_shift(@depth))[0];
       my $raw_title = $title;
       $raw_title =~ s/<[^>]+?>//g;
       if ($over >= length($raw_title) * $IndentAmount) {
           print MML "$title\t";
       } else {
           print MML "$title\n";
           print_Body(@depth);
       }
   }
   do_rest($rest,@depth);
   print_Body(@depth);
}

sub do_rest{    # the rest of the chunk handled here
   my($rest,@depth)=@_;
   my(@lines,$p,$q,$line,@paras,$inpre);
   @paras=split(/\n\n\n*/,$rest);
   for($p=0;$p<=$#paras;$p++){
       $paras[$p] =~ s/^\n//mg;        # Zap any extra empty lines.
       @lines=split(/\n/,$paras[$p]);
       if($in_mml){    # handle =for mml paragraphs
           print MML $paras[0];
           $in_html=0;
           next;
       }
       elsif($lines[0] =~ /^\s+\w*\t+.*/){  # listing or unordered list
           print_il(@depth);
           foreach $line (@lines){
               ($line =~ /^\s+(\w*)\t+(.*)/) && (($key,$rem) = ($1,$2));
               process_thing(\$rem, "MML");
               print MML defined($Podnames{$key}) ?
                   "<Marker <MType 8> <MText `gotolink $key.${doc_ext}:firstpage'>>$key\t$rem\n<par>\n" :
                       "$key\t$rem\n<par>\n";
           }
           print_Body(@depth);
       }
       elsif($lines[0] =~ /^\s/){       # preformatted code
           print_pre(@depth);
           while(defined($paras[$p])){
               @lines=split(/\n/,$paras[$p]);
               foreach $q (@lines){    # mind your p's and q's here :-)
                   $q =~ s/ /\177/g;   # hide the spaces

                   # Convert tab's to hidden spaces
                   while($q =~  s/\t+/"\177" x (length($&) * 8 - length($`) % 8)/e){
                       1;
                   }
                   process_thing(\$q,"MML");
                   $q =~ s/\177/<hardspace>/g; # make all spaces hard.
                   print MML  $q,"\n\n";       # put in extra \n to make a para
               }
               last if $paras[$p+1] !~ /^\s/;
               $p++;
           }
           print_Body(@depth);
       }
       else{                             # other text
           process_thing(\$paras[$p],"MML");
           @lines=split(/\n/,$paras[$p]);
           foreach $line (@lines){
               print MML qq{$line\n};
           }
       }
       print_Body(@depth);
   }
}

sub process_thing{      # process a chunk, order important
   my($thing,$htype)=@_;
   pre_escapes($thing);
   find_refs($thing,$htype);
   post_escapes($thing);
}

sub scan_thing{         # scan a chunk for later references
   my($cmd,$title,$pod)=@_;
   $_=$title;
   s/\n$//;
   s/E<(.*?)>/&$1;/g;
   # remove any formatting information for the headers
   s/[SFCBI]<(.*?)>/$1/g;
   # the "don't format me" thing
   s/Z<>//g;
   if ($cmd eq "item") {
       /^\*/ and  return;      # skip bullets
       /^\d+\.?/ and return;   # skip numbers
       s/(-[a-z]).*/$1/i;
       trim($_);
       return if defined($A->{$pod}->{"Items"}->{$_});
       $A->{$pod}->{"Items"}->{$_} = gensym($pod, $_);
       $index{$A->{$pod}->{"Items"}->{$_}} = $title;
       $A->{$pod}->{"Items"}->{(split(' ',$_))[0]}=$A->{$pod}->{"Items"}->{$_};
       Debug("items", "item $_");
       if (!/^-\w$/ && /([%\$\@\w]+)/ && $1 ne $_
           && !defined($A->{$pod}->{"Items"}->{$_}) && ($_ ne $1))
       {
           $A->{$pod}->{"Items"}->{$1} = $A->{$pod}->{"Items"}->{$_};
           Debug("items", "item $1 REF TO $_");
       }
       if ( m{^(tr|y|s|m|q[qwx])/.*[^/]} ) {
           my $pf = $1 . '//';
           $pf .= "/" if $1 eq "tr" || $1 eq "y" || $1 eq "s";
           if ($pf ne $_) {
               $A->{$pod}->{"Items"}->{$pf} = $A->{$pod}->{"Items"}->{$_};
               Debug("items", "item $pf REF TO $_");
           }
       }
   }
   elsif ($cmd =~ /^head[12]/){
       return if defined($A->{$pod}->{"Headers"}->{$_});
       $A->{$pod}->{"Headers"}->{$_} = gensym($pod, $_);
       $index{$A->{$pod}->{"Headers"}->{$_}} = $title;
       Debug("headers", "header $_");
   }
   else {
       (warn "unrecognized header: $cmd") if $opt_debug{'misc'};
   }
}


sub picrefs {
   my($char, $bigkey, $lilkey,$htype) = @_;
   my($key,$ref,$podname, $marker);
   for $podname ($pod,@inclusions){
       for $ref ( "Items", "Headers" ) {
           if (defined($A->{$podname}->{$ref}->{$bigkey})) {
               $value = $A->{$podname}->{$ref}->{$key=$bigkey};
               Debug("subs", "bigkey is $bigkey, value is $value\n");
           }
           elsif (defined($A->{$podname}->{$ref}->{$lilkey})) {
               $value = $A->{$podname}->{$ref}->{$key=$lilkey};
               return "" if $lilkey eq '';
               Debug("subs", "lilkey is $lilkey, value is $value\n");
           }
       }
       if (length($key)) {
           ($pod2,$num) = split(/_/,$value,2);
           $marker = print_marker($htype, $value, "$pod2.$doc_ext");
       }
   }
   if ($char =~ /[IF]/) {
       return "${marker}${lt}italic${gt}$bigkey${lt}noitalic${gt}";
   } elsif($char =~ /C/) {
       return "${marker}${lt}family Courier${gt}$bigkey${lt}family Times${gt}";
   } elsif($char =~ /S/) {
       $bigkey =~ s/ /\177/g;  # hide the spaces

       # Convert tab's to hidden spaces
       while($bigkey =~  s/\t+/"\177" x (length($&) * 8 - length($`) % 8)/e){
           1;
       }
       $bigkey =~ s/\177/${lt}hardspace${gt}/g;        # make all spaces hard.
       return "${marker}$bigkey";
   } else {
       return "${marker}${lt}bold${gt}$bigkey${lt}nobold${gt}";
   }
}

sub find_refs {
   my($thing,$htype)=@_;
   my($orig) = $$thing;
   # LREF: a manpage(3f) we don't know about
   $$thing=~s/([\$\@%](?!&[gl]t)([\w:]+|\W\b))/varrefs($1,$htype)/gems;
   $$thing=~s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))>:the I<$1>$2 manpage:gms;
   $$thing=~s/L<([^>]*)>/lrefs($1,$htype)/gems;
   $$thing=~s/([CIBF])<(\W*?(-?\w*).*?)>/picrefs($1, $2, $3, $htype)/gems;
   $$thing=~s/(S)<([^\/]\W*?(-?\w*).*?)>/picrefs($1, $2, $3, $htype)/gems;
   $$thing=~s/((\w+)\(\))/picrefs("I", $1, $2,$htype)/gems;
   (($$thing eq $orig) && ($htype eq "NAME")) &&
       ($$thing=picrefs("I", $$thing, "", $htype));
}

sub lrefs {
   my($page, $item) = split(m#/#, $_[0], 2);
   my($htype)=$_[1];
   my($podname);
   my($section) = $page =~ /\((.*)\)/;
   my $selfref;
   if ($page =~ /^[A-Z]/ && $item) {
       $selfref++;
       $item = "$page/$item";
       $page = $pod;
   }  elsif (!$item && $page =~ /[^a-z\-]/ && $page !~ /^\$.$/) {
       $selfref++;
       $item = $page;
       $page = $pod;
   }
   $item =~ s/\(\)$//;
   if (!$item) {
       if (!defined $section && defined $Podnames{$page}) {
           return print_marker("MML", "firstpage", "$page.${doc_ext}")
               . "\nthe ${lt}italic${gt}$page${lt}noitalic${gt} manpage";
       } else {
           (warn "Bizarre entry $page/$item") if $opt_debug{'misc'};
           return "the ${lt}italic${gt}$_[0]${lt}noitalic${gt}  manpage\n";
       }
   }

   if ($item =~ s/"(.*)"/$1/ || ($item =~ /[^\w\/\-]/ && $item !~ /^\$.$/)) {
       $text = "${lt}italic${gt}$item${lt}noitalic${gt}";
       $ref = "Headers";
   } else {
       $text = "${lt}italic${gt}$item${lt}noitalic${gt}";
       $ref = "Items";
   }
   for $podname ($pod, @inclusions){
       undef $value;
       if ($ref eq "Items") {
           if (defined($value = $A->{$podname}->{$ref}->{$item})) {
               ($pod2,$num) = split(/_/,$value,2);
               return print_marker(
                   ($pod eq $pod2) ?
                       $htype :
                       "MML",
                           $value, "$pod2.$doc_ext"). $text;
           }
       }
       elsif($ref eq "Headers") {
           if (defined($value = $A->{$podname}->{$ref}->{$item})) {
               ($pod2,$num) = split(/_/,$value,2);
               return print_marker(
                   ($pod eq $pod2) ?
                       $htype :
                       "MML",
                           $value, "$pod2.$doc_ext"). $text;
           }
       }
   }
   (warn "No $ref reference for $item (@_)") if $opt_debug{'misc'};
   return $text;
}

sub varrefs {
   my ($var,$htype) = @_;
   for $podname ($pod,@inclusions){
       if ($value = $A->{$podname}->{"Items"}->{$var}) {
           ($pod2,$num) = split(/_/,$value,2);
           Debug("vars", "way cool -- var ref on $var");
               return print_marker(
                   ($pod eq $pod2) ?
                       $htype :
                       "MML",
                           $value, "$pod2.$doc_ext"). $var;
       }
   }
   Debug( "vars", "bummer, $var not a var");
   return $var;
}

sub gensym {
   my ($podname, $key) = @_;
   $key =~ s/\s.*//;
   ($key = lc($key)) =~ tr/a-z/_/cs;
   my $name = "${podname}_${key}_0";
   $name =~ s/__/_/g;
   while ($sawsym{$name}++) {
       $name =~ s/_?(\d+)$/'_' . ($1 + 1)/e;
   }
   return $name;
}

sub pre_escapes {   # twiddle these, and stay up late  :-)
   my($thing)=@_;
   $$thing =~ s {
       E<
       ( [A-Za-z]+ )
       >
   } {
       do {
           exists $HTML_Escapes{$1}
               ? do { $HTML_Escapes{$1} }
               : do {
                   warn "Unknown escape: $& in $_";
                   "E<$1>";
               }
       }
   }egx;
   $$thing=~s/\\/noremap("\\\\")/eg;
   $$thing=~s/<</noremap("\\<\\<")/eg;
   $$thing=~s/^<|([^ESIBLCF])</$1 . noremap("\\<")/eg;
}
sub noremap {   # adding translator for hibit chars soon
   my $hide = $_[0];
   $hide =~ tr/\000-\177/\200-\377/;
   $hide;
}

sub post_escapes {
   my($thing)=@_;
   $$thing=~s/^>>|(?=[^GM])>>/\\>\\>/g;
   $$thing=~s/^>|([^D]?[^\\MGA])>/$1\\>/g;
   $$thing=~tr/\200-\377/\000-\177/;   # undo the noremap characters.
}

sub Debug {
   my $level = shift;
   print STDERR @_,"\n" if $opt_debug{$level};
}

sub dumptable  {
   my $t = shift;
   print STDERR "TABLE DUMP $t\n";
   foreach $k (sort keys %$t) {
       printf STDERR "%-20s <%s>\n", $t->{$k}, $k;
   }
}
sub trim {
   for (@_) {
       s/^\s+//;
       s/\s\n?$//;
   }
}

BEGIN {
%HTML_Escapes = (
   'amp'       =>      '&',    #   ampersand
   'lt'        =>      '<',    #   left chevron, less-than
   'gt'        =>      '>',    #   right chevron, greater-than
   'quot'      =>      '"',    #   double quote

   "Aacute"    =>      "${lt}Character \\xe7${gt}",    #   capital A, acute accent
   "aacute"    =>      "${lt}Character \\x87${gt}",    #   small a, acute accent
   "Acirc"     =>      "${lt}Character \\xe5${gt}",    #   capital A, circumflex accent
   "acirc"     =>      "${lt}Character \\x89${gt}",    #   small a, circumflex accent
   "AElig"     =>      '${lt}Character \\xae${gt}',    #   capital AE diphthong (ligature)
   "aelig"     =>      '${lt}Character \\xbe${gt}',    #   small ae diphthong (ligature)
   "Agrave"    =>      "${lt}Character \\xcb${gt}",    #   capital A, grave accent
   "agrave"    =>      "${lt}Character \\x88${gt}",    #   small a, grave accent
   "Aring"     =>      '${lt}Character \\x81${gt}',    #   capital A, ring
   "aring"     =>      '${lt}Character \\x8c${gt}',    #   small a, ring
   "Atilde"    =>      '${lt}Character \\xcc${gt}',    #   capital A, tilde
   "atilde"    =>      '${lt}Character \\x8b${gt}',    #   small a, tilde
   "Auml"      =>      '${lt}Character \\x80${gt}',    #   capital A, dieresis or umlaut mark
   "auml"      =>      '${lt}Character \\x8a${gt}',    #   small a, dieresis or umlaut mark
   "Ccedil"    =>      '${lt}Character \\x82${gt}',    #   capital C, cedilla
   "ccedil"    =>      '${lt}Character \\x8d${gt}',    #   small c, cedilla
   "Eacute"    =>      "${lt}Character \\x83${gt}",    #   capital E, acute accent
   "eacute"    =>      "${lt}Character \\x8e${gt}",    #   small e, acute accent
   "Ecirc"     =>      "${lt}Character \\xe6${gt}",    #   capital E, circumflex accent
   "ecirc"     =>      "${lt}Character \\x90${gt}",    #   small e, circumflex accent
   "Egrave"    =>      "${lt}Character \\xe9${gt}",    #   capital E, grave accent
   "egrave"    =>      "${lt}Character \\x8f${gt}",    #   small e, grave accent
   "Euml"      =>      "${lt}Character \\xe8${gt}",    #   capital E, dieresis or umlaut mark
   "euml"      =>      "${lt}Character \\x91${gt}",    #   small e, dieresis or umlaut mark
   "Iacute"    =>      "${lt}Character \\xea${gt}",    #   capital I, acute accent
   "iacute"    =>      "${lt}Character \\x92${gt}",    #   small i, acute accent
   "Icirc"     =>      "${lt}Character \\xeb${gt}",    #   capital I, circumflex accent
   "icirc"     =>      "${lt}Character \\x90${gt}",    #   small i, circumflex accent
   "Igrave"    =>      "${lt}Character \\xe9${gt}",    #   capital I, grave accent
   "igrave"    =>      "${lt}Character \\x93${gt}",    #   small i, grave accent
   "Iuml"      =>      "${lt}Character \\xec${gt}",    #   capital I, dieresis or umlaut mark
   "iuml"      =>      "${lt}Character \\x95${gt}",    #   small i, dieresis or umlaut mark
   "Ntilde"    =>      '${lt}Character \\x84${gt}',    #   capital N, tilde
   "ntilde"    =>      '${lt}Character \\x96${gt}',    #   small n, tilde
   "Oacute"    =>      "${lt}Character \\xee${gt}",    #   capital O, acute accent
   "oacute"    =>      "${lt}Character \\x97${gt}",    #   small o, acute accent
   "Ocirc"     =>      "${lt}Character \\xef${gt}",    #   capital O, circumflex accent
   "ocirc"     =>      "${lt}Character \\x99${gt}",    #   small o, circumflex accent
   "Ograve"    =>      "${lt}Character \\xf1${gt}",    #   capital O, grave accent
   "ograve"    =>      "${lt}Character \\x98${gt}",    #   small o, grave accent
   "Oslash"    =>      "${lt}Character \\xaf${gt}",    #   capital O, slash
   "oslash"    =>      "${lt}Character \\xbf${gt}",    #   small o, slash
   "Otilde"    =>      "${lt}Character \\xcd${gt}",    #   capital O, tilde
   "otilde"    =>      "${lt}Character \\x9b${gt}",    #   small o, tilde
   "Ouml"      =>      "${lt}Character \\x85${gt}",    #   capital O, dieresis or umlaut mark
   "ouml"      =>      "${lt}Character \\x9a${gt}",    #   small o, dieresis or umlaut mark
   "Uacute"    =>      "${lt}Character \\xf2${gt}",    #   capital U, acute accent
   "uacute"    =>      "${lt}Character \\x9c${gt}",    #   small u, acute accent
   "Ucirc"     =>      "${lt}Character \\xf3${gt}",    #   capital U, circumflex accent
   "ucirc"     =>      "${lt}Character \\x9e${gt}",    #   small u, circumflex accent
   "Ugrave"    =>      "${lt}Character \\xf4${gt}",    #   capital U, grave accent
   "ugrave"    =>      "${lt}Character \\x9d${gt}",    #   small u, grave accent
   "Uuml"      =>      "${lt}Character \\x86${gt}",    #   capital U, dieresis or umlaut mark
   "uuml"      =>      "${lt}Character \\x9f${gt}",    #   small u, dieresis or umlaut mark
   "yuml"      =>      "${lt}Character \\xd8${gt}",    #   small y, dieresis or umlaut mark
);
}