#!/usr/bin/perl
#=======================================================================
# Copyright (C) 2000-2003 Daniele Giacomini <daniele@swlibero.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Written by Daniele Giacomini <daniele@swlibero.org>
#=======================================================================
# sgmltexi-sp2texi
#
# Back-end for post-SP to Texinfo elaboration.
#
# This separate Perl program is necessary because, if included inside
# the main program, it will take away all system resources, without
# releasing them. In practice: after the call to &sgml_post_sp_elab(),
# we are not able to run makeinfo or info2dvi. The worse thing is
# that these programs die without giving valid explanations: it seems
# that there is a mistake inside the Texinfo generated source, but
# there is none.
#=======================================================================

use POSIX;
use Locale::gettext;
setlocale (LC_MESSAGES, "");
textdomain ("sgmltexi");

#sub gettext
#{
#    return $_[0];
#}

# Program executable without path.
$program_executable = $0;
$program_executable =~ m{([^/]*)$};
$program_executable = $1;

#-----------------------------------------------------------------------
# Define a temporary file.
#
# &temporary_file ()
#
sub temporary_file
{
    local( $temp_dir ) = "";
    local( $random_number ) = 0;
    local( $random_file_name ) = "";

    # Check for temp dir.
    if (-d $ENV{TEMPDIR}
        && -r $ENV{TEMPDIR}
        && -w $ENV{TEMPDIR}
        && -x $ENV{TEMPDIR})
      {
        # This directory is good.
        $temp_dir = $ENV{TEMPDIR};
      }
    elsif (-d "/tmp" && -r "/tmp" && -w "/tmp" && -x "/tmp")
      {
        # This other directory is good.
        $temp_dir = "/tmp";
      }
    elsif (-r "." && -w "." && -x ".")
      {
        # Current directory is good.
        $temp_dir = ".";
      }
    else
      {
        # We cannot use any temporary file!
        printf STDERR (gettext ("%s: cannot create any temporary file!\n"),
                       $program_executable);
        exit 1;
      }

    # If we are here, we have a valid temporary directory.
    # We try to find a good name for the file.
    while (1)
      {
        # Define the random number (six digits).
        $random_number = int ((rand) * 1000000);
        # Define the random file name: TF...tmp.
        $random_file_name = "$temp_dir/TF$random_number.tmp";
        # Check if it is new.
        if (-e $random_file_name)
          {
            # The file exists already.
            next;
          }
        else
          {
            if (open (TEMP_FILE, "> $random_file_name"))
              {
                # It works.
                close( TEMP_FILE );
                last;
              }
            else
              {
                # Don't know what to do.
                printf STDERR
                  (gettext ("%s: cannot create the temporary file %s\n"),
                   $program_executable, $random_file_name);
                next;
              }

            # This point cannot be reached.
            printf STDERR
              (gettext ("%s: function %s unknown error 1\n"),
               $program_executable, "&temporary_file()");
          }

        # This point cannot be reached.
        printf STDERR
          (gettext ("%s: function %s unknown error 2\n"),
           $program_executable, "&temporary_file()");
      }         

    # Return the file name.
    return ("$random_file_name");
}

#-----------------------------------------------------------------------
# Determinate the file name without extention.
#
# &root_name (FILE-NAME, EXTENTION)
#
sub root_name
{
    local( $file_name ) = $_[0];
    local( $extention_name ) = $_[1];
    local( $root_name ) = "";
    
    $file_name =~ m/^(.*)$extention_name$/;
    $root_name = $1;
    if ($root_name eq "")
      {
        # The extention is not the same.
        $root_name = $file_name;
      }
    return ("$root_name");
} # &root_name

#-----------------------------------------------------------------------
# Translate a positive integer into an alphabet sequence:
# from A to CZ.
#
# &integer_to_alphabet (INTEGER)
#
sub integer_to_alphabet
{
    local ($n) = $_[0];

    #-------------------------------------------------------------------
    # Generate an alphabet digit.
    # 1 -> A, 2 -> B,... 26 -> Z
    #
    # &alphabet_digit (1-26)
    #
    sub alphabet_digit
    {
        local ($digit) = $_[0];

	if ($digit == 0)
	  {
            return ("");
          }
	elsif ($digit == 1){
            return ("A");
          }
	elsif ($digit == 2)
	  {
            return ("B");
          }
        elsif ($digit == 3)
	  {
            return ("C");
          }
        elsif ($digit == 4)
          {
            return ("D");
          }
        elsif ($digit == 5)
          {
            return ("E");
          }
        elsif ($digit == 6)
          {
            return ("F");
          }
        elsif ($digit == 7)
          {
            return ("G");
          }
        elsif ($digit == 8)
          {
            return ("H");
          }
        elsif ($digit == 9)
          {
            return ("I");
          }
        elsif ($digit == 10)
          {
            return ("J");
          }
        elsif ($digit == 11)
          {
            return ("K");
          }
        elsif ($digit == 12)
          {
            return ("L");
          }
        elsif ($digit == 13)
          {
            return ("M");
          }
        elsif ($digit == 14)
          {
            return ("N");
          }
        elsif ($digit == 15)
          {
            return ("O");
          }
        elsif ($digit == 16)
          {
            return ("P");
          }
        elsif ($digit == 17)
          {
            return ("Q");
          }
        elsif ($digit == 18)
          {
            return ("R");
          }
        elsif ($digit == 19)
          {
            return ("S");
          }
        elsif ($digit == 20)
          {
            return ("T");
          }
        elsif ($digit == 21)
          {
            return ("U");
          }
        elsif ($digit == 22)
          {
            return ("V");
          }
        elsif ($digit == 23)
          {
            return ("W");
          }
        elsif ($digit == 24)
          {
            return ("X");
          }
        elsif ($digit == 25)
          {
            return ("Y");
          }
        elsif ($digit == 26)
          {
            return ("Z");
          }
    }

    # Analyze the number.
    if ($n <= 0)
      {
        # We cannot translate zero or negative numbers.
        $return = "##<A##";
      }
    elsif ($n <= 26)
      {
        # We have only one letter.
        $return = &alphabet_digit($n);
      }
    elsif ($n <= 52)
      {
        # We have two letters: Ax.
        $n = $n - 26;
        $return = "A" . &alphabet_digit($n);
      }
    elsif ($n <= 78)
      {
        # We have two letters: Bx.
        $n = $n - 52;
        $return = "B" . &alphabet_digit($n);

      }
    elsif ($n <= 104)
      {
        # We have two letters: Cx.
        $n = $n - 78;
        $return = "C" . &alphabet_digit($n);
      }
    else
      {
        # The number is too big.
        $return = "##>CZ##";
      }
} # &integer_to_alphabet

#-----------------------------------------------------------------------
# Translate a positive integer into a roman string.
#
# &integer_to_roman (INTEGER)
#
sub integer_to_roman
{
    local ( $n ) = $_[0];;
    local ( $digit_1 ) = 0;
    local ( $digit_2 ) = 0;
    local ( $digit_3 ) = 0;
    local ( $digit_4 ) = 0;

    #-------------------------------------------------------------------
    # First digit into roman: 1-9
    #
    sub digit_1_to_roman
    {
        local ( $digit ) = $_[0];

        if ($digit == 0)
	  {
            return ("");
          }
        elsif ($digit == 1)
          {
            return ("I");
          }
        elsif ($digit == 2)
          {
            return ("II");
          }
        elsif ($digit == 3)
          {
            return ("III");
          }
        elsif ($digit == 4)
          {
            return ("IV");
          }
        elsif ($digit == 5)
          {
            return ("V");
          }
        elsif ($digit == 6)
          {
            return ("VI");
          }
        elsif ($digit == 7)
          {
            return ("VII");
          }
        elsif ($digit == 8)
          {
            return ("VIII");
          }
        elsif ($digit == 9)
          {
            return ("IX");
          }
    }

    #-------------------------------------------------------------------
    # Second digit into roman: 10-90
    #
    sub digit_2_to_roman
    {
        local ($digit) = $_[0];

        if ($digit == 0)
	  {
            return ("");
          }
        elsif ($digit == 1)
          {
            return ("X");
          }
        elsif ($digit == 2)
	  {
            return ("XX");
          }
        elsif ($digit == 3)
	  {
            return ("XXX");
          }
        elsif ($digit == 4)
	  {
            return ("XL");
          }
        elsif ($digit == 5)
	  {
            return ("L");
          }
        elsif ($digit == 6)
	  {
            return ("LX");
          }
        elsif ($digit == 7)
	  {
            return ("LXX");
          }
        elsif ($digit == 8)
	  {
            return ("LXXX");
          }
        elsif ($digit == 9)
	  {
            return ("XC");
          }
    }

    #-------------------------------------------------------------------
    # Third digit into roman: 100-900
    #
    sub digit_3_to_roman
    {
        local ($digit) = $_[0];

        if ($digit == 0)
   	  {
            return ("");
          }
        elsif ($digit == 1)
          {
            return ("C");
          }
        elsif ($digit == 2)
          {
            return ("CC");
          }
        elsif ($digit == 3)
          {
            return ("CCC");
          }
        elsif ($digit == 4)
          {
            return ("CD");
          }
        elsif ($digit == 5)
          {
            return ("D");
          }
        elsif ($digit == 6)
          {
            return ("DC");
          }
        elsif ($digit == 7)
          {
            return ("DCC");
          }
        elsif ($digit == 8)
          {
            return ("DCCC");
          }
        elsif ($digit == 9)
          {
            return ("CM");
          }
    }

    #-------------------------------------------------------------------
    # Fourth digit into roman: 1000-9000
    #
    sub digit_4_to_roman
    {
        local ($digit) = $_[0];

        if ($digit == 0)
	  {
            return ("");
          }
        elsif ($digit == 1)
          {
            return ("M");
          }
        elsif ($digit == 2)
          {
            return ("MM");
          }
        elsif ($digit == 3)
          {
            return ("MMM");
          }
        elsif ($digit == 4)
          {
            return ("MMMM");
          }
        elsif ($digit == 5)
          {
            return ("MMMMM");
          }
        elsif ($digit == 6)
          {
            return ("MMMMMM");
          }
        elsif ($digit == 7)
          {
            return ("MMMMMMM");
          }
        elsif ($digit == 8)
          {
            return ("MMMMMMMM");
          }
        elsif ($digit == 9)
          {
            return ("MMMMMMMMM");
          }
    }

    # Start the work.
    $digit_4 = int( $n / 1000 );
    $n = ($n - $digit_4*1000);
    $digit_3 = int( $n / 100 );
    $n = ($n - $digit_3*100);
    $digit_2 = int( $n / 10 );
    $n = ($n - $digit_2*10);
    $digit_1 = $n;

    return (&digit_4_to_roman($digit_4)
            . &digit_3_to_roman($digit_3)
            . &digit_2_to_roman($digit_2)
            . &digit_1_to_roman($digit_1));
}

#-----------------------------------------------------------------------
# Diagnostic output; it depends on the following global variables:
#   $verbose
#   $root_file_name
#
sub diag_output
{
    local ($string)    = $_[0];

    # Append to the diagnostic file.
    open (DIAG, ">> $root_file_name.diag");
    
    if ($verbose)
      {
        print STDOUT ($string);
      }
    # In any case, print it on the DIAG file
    print DIAG ($string);

    # Close the file.
    close (DIAG);

}

#-----------------------------------------------------------------------
# SGML post-SP elaboration.
#
# This function elaborate a post-SP output (the SGML parser), and
# take actions.
#
# &sgml_post_sp_elab (INPUT-POST-SP,
#                     TARGET,
#                     ORIGINAL_FILE_NAME,
#                     ROOT-NAME,
#                     PAPER,
#                     SETCHAPTERNEWPAGE,
#                     FOOTNOTESTYLE,
#                     HEADINGS,
#                     OUTPUT_ENCODING)
#
sub sgml_post_sp_elab
{
    #-------------------------------------------------------------------
    # Arguments.
    #-------------------------------------------------------------------

    # Post-SP input file.
    local ($input_file) = $_[0];

    # The target definition: this name is used to alter the
    # final transformation
    local ($target) = $_[1];

    # Original file name to tell informations.
    local ($original_file_name) = $_[2];

    # A name used to construct the final result.
    local ($root_file_name) = $_[3];

    # The paper format.
    local ($paper) = $_[4];

    # The @setchapternewpage command.
    local ($setchapternewpage) = $_[5];

    # The @footnotestyle command.
    local ($footnotestyle) = $_[6];

    # The @headings command.
    local ($headings) = $_[7];

    # The @documentencoding command.
    local ($output_encoding) = $_[8];

    #-------------------------------------------------------------------
    # More local variables.
    #-------------------------------------------------------------------

    # We need to define a reference for an input stream.
    # The choice to use the same file names is just one way to
    # be sure to have ever different names.
    # We could use a random number, maybe.
    #This is useful for recursive call; for this function, there is no
    # need to use this technique; this is only a way to use uniform code.
    local ($input_stream) = "$input_file";

    # This is a reference for the current output stream.
    # This reference is used by the output() sub-function.
    local ($current_output_stream) = "";

    # Output stack for controlling the output stream.
    @output_stack = ();

    # The line read.
    local ($line) = "";

    # Parsed character text.
    local ($pcdata) = "";

    # An associative array to receive the SGML element attribute.
    %element_attribute = ();

    #-------------------------------------------------------------------
    # Local variables specific for the Texinfo composition process.
    #-------------------------------------------------------------------

    # Title counters.
    local ($intro) = 0;
    local ($tome) = 0;
    local ($part) = 0;
    local ($chapter) = 0;
    local ($appendix) = 0;
    local ($sect1) = 0;         
    local ($sect2) = 0;         
    local ($sect3) = 0;         
    local ($index) = 0;
    local ($unnumbered) = 0;
    
    # Current level:
    #       intro-h1
    #         intro-h2
    #           intro-h3
    #             intro-h4
    #   tome
    #     part
    #       chapter-h1, chapter-u-h1
    #         chapter-h2, chapter-u-h2
    #           chapter-h3, chapter-u-h3
    #             chapter-h4, chapter-u-h4
    #       appendix-h1, appendix-u-h1
    #         appendix-h2, appendix-u-h2
    #           appendix-h3, appendix-u-h3
    #             appendix-h4, appendix-h4
    #       index
    local ($current_level) = "";
    
    # Current document position:
    #   head
    #   intro
    #   body
    #   appendix
    local ($document_position) = "";
        
    # This is about multitables:
    # have we already started a column fractions information?
    local ($columnfractions) = 0;
    
    # Head informations.
    local ($documentlanguage) = "";     # it can be empty.
    local ($documentencoding) = "";     # it can be empty.
    local ($documentspacing) = "";      # it can be empty.
    local ($setfilename) = "";          # required
    local ($settitle) = "";             # required
    local ($documentdescription) = "";  # it can be empty.
    local (@syncodeindexfrom) = ();
    local (@syncodeindexto) = ();
    local (@synindexfrom) = ();
    local (@synindexto) = ();
    local (@defcodeindex) = ();
    local (@defindex) = ();
    local ($infodir_category) = "";
    local ($infodir_contents) = "";

    # Titlepage.
    local ($title) = "";
    local (@subtitles) = ();
    local ($abstract) = "";
    local (@authors) = ();
    local ($front_cover_text) = "";
    local ($extra_after_cover) = "";
    local (@copyrights) = ();
    local ($license) = "";
    local ($coverart) = "";
    local ($publishnote) = "";
    local ($legal) = "";
    local ($extra_after_legal) = "";
    local ($dedications) = "";
    local ($extra_after_dedications) = "";
    local ($tp_current_position) = ""; # cover, legal, dedications

    # Table of contents.
    local ($contents) = 0;
    local ($shortcontents) = 0;
    local ($summarycontents) = 0;

    # Top node pointers, with defaults.
    local ($top_node_next) = "Top";
    local ($top_node_previous) = "Top";
    local ($top_node_up) = "(dir)";
        
    # Headers title informations.
    local ($tome_heading_title) = "";
    local ($tome_heading_anchor) = "";
    local ($tome_heading_node) = "";
    local ($tome_heading_menu) = "";
    local ($tome_heading_next) = "";
    local ($tome_heading_prev) = "";
    local ($tome_heading_up) = "";
    local ($part_heading_title) = "";
    local ($part_heading_anchor) = "";
    local ($part_heading_node) = "";
    local ($part_heading_menu) = "";
    local ($part_heading_next) = "";
    local ($part_heading_prev) = "";
    local ($part_heading_up) = "";
    local ($h1_title) = "";
    local ($h1_anchor) = "";
    local ($h1_node) = "";
    local ($h1_menu) = "";
    local ($h1_next) = "";
    local ($h1_prev) = "";
    local ($h1_up) = "";
    local ($h1_type) = "";
    local ($h2_title) = "";
    local ($h2_anchor) = "";
    local ($h2_node) = "";
    local ($h2_menu) = "";
    local ($h2_next) = "";
    local ($h2_prev) = "";
    local ($h2_up) = "";
    local ($h2_type) = "";
    local ($h3_title) = "";
    local ($h3_anchor) = "";
    local ($h3_node) = "";
    local ($h3_menu) = "";
    local ($h3_next) = "";
    local ($h3_prev) = "";
    local ($h3_up) = "";
    local ($h3_type) = "";
    local ($h4_title) = "";
    local ($h4_anchor) = "";
    local ($h4_node) = "";
    local ($h4_menu) = "";
    local ($h4_next) = "";
    local ($h4_prev) = "";
    local ($h4_up) = "";
    local ($h4_type) = "";
    local ($index_heading_title) = "";
    local ($index_heading_anchor) = "";
    local ($index_heading_node) = "";
    local ($index_heading_menu) = "";
    local ($index_heading_next) = "";
    local ($index_heading_prev) = "";
    local ($index_heading_up) = "";

    #-------------------------------------------------------------------
    # Information about Info menus.
    #-------------------------------------------------------------------

    # This array is used to remember where appeared the last
    # useful menu elements.
    # Actually, if an h2 header has a menu, also h1 should have,
    # but here we don't want to impose this.
    #
    @info_menu_levels = (1,         # Top is usually true.
                         0,         # tome
                         0,         # part
                         0,         # intro, h1, appendix, index
                         0,         # h2
                         0);        # h3

    # These two associative array are used to store all the menus.
    # The key is a name obtained from &short_level_description ().
    %info_auto_menus = ();          # from current heading level to auto Info menu
    %info_manual_menus = ();        # from current heading level to manual Info menu

    # This variable is used as the key for the previous associative
    # arrays. It stores the current info menu name.
    $current_info_menu = "";

    # This array is used to remember previous $current_info_menu values.
    @current_info_menu_list = ();

    # This array is used to remember all menu created.
    @list_info_menu = ();

    # Menu counter for @list_info_menu. Zero is right in this context.
    $menu_counter = 0;


    #-------------------------------------------------------------------
    # Sub functions.
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # This function is like print, but may redirect output to a stack
    # waiting to have more data.
    #
    # &output ( STRING );
    #
    sub output
    {
        local ($output_line) = $_[0];
        
        if ($#output_stack >= 0)
          {
            # Output must be added to the top element of the stack.
            $output_stack[$#output_stack] = $output_stack[$#output_stack]
                                            . $output_line;
          }
        else
          {
            # Output is sent to the output stream.
            print $current_output_stream ($output_line);
          }
    }

    #-------------------------------------------------------------------
    # Direct the output stream into another stack level.
    #
    # &push_output ();
    #
    sub push_output
    {
        # Add one empty element at the top of the stack.
        $output_stack[$#output_stack+1] = "";
    }

    #-------------------------------------------------------------------
    # Extract the last stack level.
    #
    # &pop_output ();
    #
    sub pop_output
    {
        # Check if it is possible.
        if ($#output_stack >= 0)
          {
            # Extract one element at the top of the stack.
            local ($output_line) = $output_stack[$#output_stack];
            $#output_stack--;
            return ($output_line);
          }
        else
          {
            # The stack is empty.
            return ("");
          }
    }

    #-------------------------------------------------------------------
    # Translate some definitions into different languages.
    #
    # We cannot use gettext(), because this is controlled by a
    # command inside the text, and we cannot change the language
    # from here. The text may be written in a different language
    # than the actual locale configuration.
    #-------------------------------------------------------------------
    sub tome_def
    {
        if ($documentlanguage eq "it")
          {
            return "tomo";
          }
	else
	  {
            return "tome";
          }
    }
    sub part_def
    {
        if ($documentlanguage eq "it")
          {
            return "parte";
          }
        else
          {
        return "part";
          }
    }
    sub intro_def
    {
        if ($documentlanguage eq "it")
          {
            return "introduzione";
          }
        else
          {
            return "introduction";
          }
    }
    sub chapter_def
    {
        if ($documentlanguage eq "it")
          {
            return "capitolo";
          }
        else
          {
            return "chapter";
          }
    }
    sub appendix_def
    {
	if ($documentlanguage eq "it")
	  {
            return "appendice";
          }
        else
          {
            return "appendix";
          }
    }
    sub section_def
    {
        if ($documentlanguage eq "it")
          {
            return "sezione";
          }
        else
          {
            return "section";
        }
    }
    sub subsection_def
    {
        if ($documentlanguage eq "it")
          {
            return "sottosezione";
          }
        else
          {
            return "subsection";
          }
    }
    sub subsubsection_def
    {
        if ($documentlanguage eq "it")
          {
            return "sotto-sottosezione";
          }
        else
          {
            return "sub-subsection";
          }
    }
    sub index_def
    {
        if ($documentlanguage eq "it")
          {
            return "indice analitico";
          }
        else
          {
            return "index";
          }
    }
    sub short_tome_def
    {
        if ($documentlanguage eq "it")
          {
            return "tomo";
          }
        else
          {
            return "tome";
          }
    }
    sub short_part_def
    {
        if ($documentlanguage eq "it")
          {
            return "parte";
          }
        else
          {
            return "part";
          }
    }
    sub short_intro_def
    {
        if ($documentlanguage eq "it")
          {
            return "intro";
          }
        else
          {
            return "intro";
          }
    }
    sub short_chapter_def
    {
        if ($documentlanguage eq "it")
          {
            return "cap";
          }
        else
          {
            return "chap";
          }
    }
    sub short_appendix_def
    {
        if ($documentlanguage eq "it")
          {
            return "app";
          }
        else
          {
            return "app";
          }
    }
    sub short_section_def
    {
        if ($documentlanguage eq "it")
          {
            return "sez";
          }
        else
          {
            return "sect";
          }
    }
    sub short_subsection_def
    {
        if ($documentlanguage eq "it")
          {
            return "sez";
          }
        else
          {
            return "sect";
          }
    }
    sub short_subsubsection_def
    {
       if ($documentlanguage eq "it")
          {
            return "sez";
          }
        else
          {
            return "sect";
          }
    }
    sub short_index_def
    {
        if ($documentlanguage eq "it")
          {
            return "ind";
          }
        else
          {
            return "ind";
          }
    }

    #-------------------------------------------------------------------
    # Create a short level description.
    #
    # &short_level_description ()
    #
    sub short_level_description
    {
        if ($current_level eq "intro-h1")
          {
            return &short_intro_def () . " " . "$intro";
          }
        elsif ($current_level eq "intro-h2")
          {
            return &short_intro_def () . " " . "$intro.$sect1";
          }
        elsif ($current_level eq "intro-h3")
          {
            return &short_intro_def () . " " . "$intro.$sect1.$sect2";
          }
        elsif ($current_level eq "intro-h4")
          {
            return &short_intro_def () . " " . "$intro.$sect1.$sect2.$sect3";
          }
        elsif ($current_level eq "tome")
          {
            return &short_tome_def () . " " .  &integer_to_roman($tome);
          }
        elsif ($current_level eq "part" )
          {
            return &short_part_def () . " " . &integer_to_roman($part);
          }
        elsif ($current_level eq "chapter-h1" )
          {
            return &short_chapter_def () . " " . "$chapter";
          }
        elsif ($current_level eq "chapter-u-h1" )
          {
            return &short_chapter_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "chapter-h2" )
          {
            return &short_section_def () . " " . "$chapter.$sect1";
          }
        elsif ($current_level eq "chapter-u-h2" )
          {
            return &short_section_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "chapter-h3" )
          {
            return &short_subsection_def () . " " . "$chapter.$sect1.$sect2";
          }
        elsif ($current_level eq "chapter-u-h3" )
          {
            return &short_subsection_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "chapter-h4" )
          {
            return &short_subsubsection_def () . " " . "$chapter.$sect1.$sect2.$sect3";
          }
        elsif ($current_level eq "chapter-u-h4" )
          {
            return &short_subsubsection_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "appendix-h1" )
          {
            return &short_appendix_def () . " " . &integer_to_alphabet($appendix);
          }
        elsif ($current_level eq "appendix-u-h1" )
          {
            return &short_appendix_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "appendix-h2" )
          {
            return &short_appendix_def () . " " . &integer_to_alphabet($appendix) . "$sect1";
          }
        elsif ($current_level eq "appendix-u-h2" )
          {
            return &short_appendix_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "appendix-h3" )
          {
            return &short_appendix_def () . " " . &integer_to_alphabet($appendix) . "$sect1.$sect2";
          }
        elsif ($current_level eq "appendix-u-h3" )
          {
            return &short_appendix_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "appendix-h4" )
          {
            return &short_appendix_def () . " " . &integer_to_alphabet($appendix) . "$sect1.$sect2.$sect3";
          }
        elsif ($current_level eq "appendix-u-h4" )
          {
            return &short_appendix_def () . " u" . "$unnumbered";
          }
        elsif ($current_level eq "index" )
          {
            return &short_index_def () . " " . $index;
          }
        else
          {
            return "## unknown sectioning ##";
          }
    }


    #-------------------------------------------------------------------
    # This is the pre-elaboration process.
    #
    # &sgml_tag_elab_first_pass (TYPE,
    #                            ELEMENT,
    #                            %ATTRIBUTES,
    #                            TARGET,
    #                            ORIGINAL_NAME,
    #                            ROOT_FILE_NAME,
    #                            PAPER,
    #                            SETCHAPTERNEWPAGE,
    #                            FOOTNOTESTYLE,
    #                            HEADINGS,
    #                            OUTPUT_ENCODING)
    #
    sub sgml_tag_elab_first_pass
    {
    
        #---------------------------------------------------------------
        # Function arguments.
        #---------------------------------------------------------------

        local ($type) = $_[0];
        local ($element) = $_[1];
        local ($attributes) = $_[2];
        local ($target) = $_[3];
        local ($original_file_name) = $_[4];
        local ($root_file_name) = $_[5];
        local ($paper) = $_[6];
        local ($setchapternewpage) = $_[7];
        local ($footnotestyle) = $_[8];
        local ($headings) = $_[9];
        local ($output_encoding) = $_[10];


        if ($element eq "SGMLTEXI")
          {
            if ($type eq "start")
              {
                # Save the document language information.
                $documentlanguage = ${$attributes}{'LANG'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "HEAD")
          {
            if ($type eq "start")
              {
                # Save the document position.
                $document_position = "head";
              }
            else
              {
                # Prepare the Top menu.
                $info_menu_levels[0] = 1;
                $current_info_menu = "top";
                $#current_info_menu_list = 0;
                $current_info_menu_list[0] = $current_info_menu;
                $#list_info_menu = 0;
                $list_info_menu[0] = $current_info_menu;
              }
          }
        elsif ($element eq "ADMIN")
          {
            # Nothing to do.
            ;
          }
        elsif ($element eq "MENU")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Which is the current menu?
                if ($current_level eq "")
                  {
                    # This is the top level.
                    # Just say that it is the top.
                    $current_info_menu = "top";
                  }
                else
                  {
                    # We need to update info menu information.
                    $current_info_menu = &short_level_description;
                    # Add the name inside the @current_info_menu_list.
                    $#current_info_menu_list++;
                    $current_info_menu_list[$#current_info_menu_list]
                      = $current_info_menu;
                    # Add the name inside the @list_info_menu.
                    $#list_info_menu++;
                    $list_info_menu[$#list_info_menu]
                      = $current_info_menu;
                
                    # Prepare the menu.
                    if ($current_level eq "tome")
                      {
                        $info_menu_levels[1] = 1;
                      }
                    elsif ($current_level eq "part")
                      {
                        $info_menu_levels[2] = 1;
                      }
                    elsif ($current_level eq "chapter-h1"
                           || $current_level eq "chapter-u-h1"
                           || $current_level eq "intro-h1"
                           || $current_level eq "appendix-h1"
                           || $current_level eq "appendix-u-h1"
                           || $current_level eq "index")
                      {
                        $info_menu_levels[3] = 1;
                      }
                    elsif ($current_level eq "chapter-h2"
                           || $current_level eq "chapter-u-h2"
                           || $current_level eq "intro-h2"
                           || $current_level eq "appendix-h2"
                           || $current_level eq "appendix-u-h2")
                      {
                        $info_menu_levels[4] = 1;
                      }
                    elsif ($current_level eq "chapter-h3"
                           || $current_level eq "chapter-u-h3"
                           || $current_level eq "intro-h3"
                           || $current_level eq "appendix-h3"
                           || $current_level eq "appendix-u-h3")
                      {
                        $info_menu_levels[5] = 1;
                      }
                  }

                # Save a new Info menu.
                $info_manual_menus{$current_info_menu} = &pop_output ();
              }
          }
        elsif ($element eq "INTRO")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "intro";
              }
            else
              {
                # Make a separation inside the Info menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "\n";
              }
          }
        elsif ($element eq "BODY")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "body";
              }
            else
              {
                # Make a separation inside the Info menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "\n";
              }
          }
        elsif ($element eq "APPENDIX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "appendix";
              }
            else
              {
                # Make a separation inside the Info menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "\n";
              }
          }
        elsif ($element eq "TOMEHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $tome_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $tome_heading_node = ${$attributes}{'NODE'};
                $tome_heading_menu = ${$attributes}{'MENU'};
                # Here start a tome. Do some preparations.
                # Tome happens only inside a body.
                $current_level = "tome";
                $tome++;
                # part counter doesn't change.
                # chapter counter doesn't change.
                $sect1 = 0;		
                $sect2 = 0;		
                $sect3 = 0;		

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";
                local ($levels) = 0;

                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[2] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[2] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[1] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[1] = 0;
                    # increment levels to restore;
                    $levels++;
                  }

                # Restore current info menu if necessary.
                if ($levels > 0)
                  {
                    # The @current_info_menu_list array must be
                    # reduced.
                    $#current_info_menu_list
                      = $#current_info_menu_list - $levels;

                    # Now, the last valid $current_info_menu
                    # value is restored.
                    $current_info_menu
                      = $current_info_menu_list[$#current_info_menu_list];
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $tome_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($tome_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $tome_heading_node = &short_level_description;
                  }
                # Add necessary spaces.        
                $node_with_spaces
                  = "* $tome_heading_node" . "::                    ";
                $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                # Check if we have a special menu description.
                if ($tome_heading_menu eq "")
                  {
                    # Use the title instead.
                    $tome_heading_menu = $tome_heading_title;
                  }
                
                # Add an item into the node menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "$node_with_spaces$tome_heading_menu\n";
              }
          }
        elsif ($element eq "PARTHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $part_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $part_heading_node = ${$attributes}{'NODE'};
                $part_heading_menu = ${$attributes}{'MENU'};
                # Here start a part. Do some preparations.
                # Tome happens only inside a body.
                $current_level = "part";
                $part++;
                # chapter counter doesn't change.
                $sect1 = 0;		
                $sect2 = 0;		
                $sect3 = 0;		

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";
                local ($levels) = 0;

                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[2] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[2] = 0;
                    # increment levels to restore;
                    $levels++;
                  }

                # Restore current info menu if necessary.
                if ($levels > 0)
                  {
                    # The @current_info_menu_list array must be
                    # reduced.
                    $#current_info_menu_list
                      = $#current_info_menu_list - $levels;

                    # Now, the last valid $current_info_menu
                    # value is restored.
                    $current_info_menu
                      = $current_info_menu_list[$#current_info_menu_list];
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $part_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($part_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $part_heading_node = &short_level_description;
                  }
                # Add necessary spaces.        
                $node_with_spaces
                  = "* $part_heading_node" . "::                    ";
                $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                # Check if we have a special menu description.
                if ($part_heading_menu eq "")
                  {
                    # Use the title instead.
                    $part_heading_menu = $part_heading_title;
                  }

                # Add an item into the node menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "$node_with_spaces$part_heading_menu\n";
              }
          }
        elsif ($element eq "H1")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h1_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h1_node = ${$attributes}{'NODE'};
                $h1_menu = ${$attributes}{'MENU'};
                $h1_type = lc ${$attributes}{'TYPE'};
                # Here start a chapter. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h1";
        	    $intro++;
        	    $sect1 = 0;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h1_type eq "unnumbered"
                        || $h1_type eq "heading")
                      {
        	        $current_level = "chapter-u-h1";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h1";
        	        $chapter++;
                      }

        	    $sect1 = 0;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h1_type eq "unnumbered"
                        || $h1_type eq "heading")
                      {
        	        $current_level = "appendix-u-h1";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h1";
        	        $appendix++;
                      }

        	    $sect1 = 0;
        	    $sect2 = 0;
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";
                local ($levels) = 0;

                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                    # increment levels to restore;
                    $levels++;
                  }

                # Restore current info menu if necessary.
                if ($levels > 0)
                  {
                    # The @current_info_menu_list array must be
                    # reduced.
                    $#current_info_menu_list
                      = $#current_info_menu_list - $levels;

                    # Now, the last valid $current_info_menu
                    # value is restored.
                    $current_info_menu
                      = $current_info_menu_list[$#current_info_menu_list];
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h1_title = &pop_output ();

                # Check if the node name is required.
                if ($h1_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $h1_node = &short_level_description;
                  }
                # Add necessary spaces.        
                $node_with_spaces
                  = "* $h1_node" . "::                    ";
                $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                # Check if we have a special menu description.
                if ($h1_menu eq "")
                  {
                    # Use the title instead.
                    $h1_menu = $h1_title;
                  }

                # Add an item into the node menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "$node_with_spaces$h1_menu\n";
              }
          }
        elsif ($element eq "H2")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h2_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h2_node = ${$attributes}{'NODE'};
                $h2_menu = ${$attributes}{'MENU'};
                $h2_type = lc ${$attributes}{'TYPE'};
                # Here start a section. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h2";
        	    $sect1++;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h2_type eq "unnumbered"
                        || $h2_type eq "heading")
                      {
        	        $current_level = "chapter-u-h2";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h2";
                 	$sect1++;
                      }

        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h2_type eq "unnumbered"
                        || $h2_type eq "heading")
                      {
        	        $current_level = "appendix-u-h2";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h2";
        	        $sect1++;
                      }

        	    $sect2 = 0;
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";
                local ($levels) = 0;

                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                    # increment levels to restore;
                    $levels++;
                  }

                # Restore current info menu if necessary.
                if ($levels > 0)
                  {
                    # The @current_info_menu_list array must be
                    # reduced.
                    $#current_info_menu_list
                      = $#current_info_menu_list - $levels;

                    # Now, the last valid $current_info_menu
                    # value is restored.
                    $current_info_menu
                      = $current_info_menu_list[$#current_info_menu_list];
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h2_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[3])
                  {
                    if ($h2_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h2_node = &short_level_description;
                      }

                    # Add necessary spaces.        
                    $node_with_spaces
                      = "* $h2_node" . "::                    ";
                    $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                    # Check if we have a special menu description.
                    if ($h2_menu eq "")
                      {
                        # Use the title instead.
                        $h2_menu = $h2_title;
                      }

                    # Add an item into the node menu.
                    $info_auto_menus{$current_info_menu}
                      = $info_auto_menus{$current_info_menu}
                        . "$node_with_spaces$h2_menu\n";

                    # Print the node name.
                    &output ("\n\@node $h2_node");
                  }
              }
          }
        elsif ($element eq "H3")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h3_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h3_node = ${$attributes}{'NODE'};
                $h3_menu = ${$attributes}{'MENU'};
                $h3_type = lc ${$attributes}{'TYPE'};
                # Here start a subsection. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h3";
        	    $sect2++;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h3_type eq "unnumbered"
                        || $h3_type eq "heading")
                      {
        	        $current_level = "chapter-u-h3";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h3";
        	        $sect2++;		
                      }

        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h3_type eq "unnumbered"
                        || $h3_type eq "heading")
                      {
        	        $current_level = "appendix-u-h3";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h3";
        	        $sect2++;
                      }
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";
                local ($levels) = 0;

                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                    # increment levels to restore;
                    $levels++;
                  }

                # Restore current info menu if necessary.
                if ($levels > 0)
                  {
                    # The @current_info_menu_list array must be
                    # reduced.
                    $#current_info_menu_list
                      = $#current_info_menu_list - $levels;

                    # Now, the last valid $current_info_menu
                    # value is restored.
                    $current_info_menu
                      = $current_info_menu_list[$#current_info_menu_list];
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h3_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[4])
                  {
                    if ($h3_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h3_node = &short_level_description;
                      }

                    # Add necessary spaces.        
                    $node_with_spaces
                      = "* $h3_node" . "::                    ";
                    $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                    # Check if we have a special menu description.
                    if ($h3_menu eq "")
                      {
                        # Use the title instead.
                        $h3_menu = $h3_title;
                      }

                    # Add an item into the node menu.
                    $info_auto_menus{$current_info_menu}
                      = $info_auto_menus{$current_info_menu}
                        . "$node_with_spaces$h3_menu\n";

                    # Print the node name.
                    &output ("\n\@node $h3_node");
                  }
              }
          }
        elsif ($element eq "H4")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h4_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h4_node = ${$attributes}{'NODE'};
                $h4_menu = ${$attributes}{'MENU'};
                $h4_type = lc ${$attributes}{'TYPE'};
                # Here start a sub-subsection. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h4";
        	    $sect3++;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h4_type eq "unnumbered"
                        || $h4_type eq "heading")
                      {
        	        $current_level = "chapter-u-h4";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h4";
        	        $sect3++;		
                      }
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h4_type eq "unnumbered"
                        || $h4_type eq "heading")
                      {
        	        $current_level = "appendix-u-h4";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h4";
        	        $sect3++;
                      }
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h4_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[5])
                  {
                    if ($h4_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h4_node = &short_level_description;
                      }

                    # Add necessary spaces.        
                    $node_with_spaces
                      = "* $h4_node" . "::                    ";
                    $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                    # Check if we have a special menu description.
                    if ($h4_menu eq "")
                      {
                        # Use the title instead.
                        $h4_menu = $h4_title;
                      }

                    # Add an item into the node menu.
                    $info_auto_menus{$current_info_menu}
                      = $info_auto_menus{$current_info_menu}
                        . "$node_with_spaces$h4_menu\n";

                    # Print the node name.
                    &output ("\n\@node $h4_node");
                  }
              }
          }
        elsif ($element eq "INDEXHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $index_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $index_heading_node = ${$attributes}{'NODE'};
                $index_heading_menu = ${$attributes}{'MENU'};
                # Here start an index. Do some preparations.
        	$current_level = "index";
        	$index++;
                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                local ($node_with_spaces) = "";

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $index_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($index_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $index_heading_node = &short_level_description;
                  }
                # Add necessary spaces.        
                $node_with_spaces
                  = "* $index_heading_node" . "::                    ";
                $node_with_spaces = substr( $node_with_spaces, 0, 20 );

                # Check if we have a special menu description.
                if ($index_heading_menu eq "")
                  {
                    # Use the title instead.
                    $index_heading_menu = $index_heading_title;
                  }

                # Add an item into the node menu.
                $info_auto_menus{$current_info_menu}
                  = $info_auto_menus{$current_info_menu}
                    . "$node_with_spaces$index_heading_menu\n";
              }
          }
	else
	  {
	    &sgml_tag_elab_basic
		($type,
		 $element,
		 $attributes,
                 $target,
		 $original_file_name,
                 $root_file_name,
		 $paper,
                 $setchapternewpage,
                 $footnotestyle,
                 $headings,
		 $output_encoding);
	  }
    }

    #-------------------------------------------------------------------
    # Standard element elaboration subroutine.
    #
    # &sgml_tag_elab_basic (TYPE,
    #                       ELEMENT,
    #                       %ATTRIBUTES,
    #                       TARGET,
    #                       ORIGINAL_NAME,
    #                       ROOT_FILE_NAME,
    #                       PAPER,
    #                       SETCHAPTERNEWPAGE,
    #                       FOOTNOTESTYLE,
    #                       HEADINGS,
    #                       OUTPUT_ENCODING)
    #
    sub sgml_tag_elab_basic
    {
    
        #---------------------------------------------------------------
        # Function arguments.
        #---------------------------------------------------------------

        local ($type) = $_[0];
        local ($element) = $_[1];
        local ($attributes) = $_[2];
        local ($target) = $_[3];
        local ($original_file_name) = $_[4];
        local ($root_file_name) = $_[5];
        local ($paper) = $_[6];
        local ($setchapternewpage) = $_[7];
        local ($footnotestyle) = $_[8];
        local ($headings) = $_[9];
        local ($output_encoding) = $_[10];


        #---------------------------------------------------------------
        # Element handlers.
        # Element names and attribute names are uppercase.
        #---------------------------------------------------------------

        if ($element eq "DETAILMENU")
          {
            # DETAILMENU is enclosed inside MENU
            if ($type eq "start")
              {
                &output ("\@detailmenu\n");
              }
            else
              {
                &output ("\@end detailmenu\n");
              }
          }
        elsif ($element eq "CODE")
          {
            if ($type eq "start")
              {
                &output ("\@code{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "KBD")
          {
            if ($type eq "start")
              {
                &output ("\@kbd{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "KBDINPUTSTYLE")
          {
            if ($type eq "start")
              {
                local ($kbdinputstyle) = "";
                $kbdinputstyle = lc ${$attributes}{'STYLE'};
                &output ("\n\@kbdinputstyle $kbdinputstyle");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "KEY")
          {
            if ($type eq "start")
              {
                &output ("\@key{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "SAMP")
          {
            if ($type eq "start")
              {
                &output ("\@samp{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "VAR")
          {
            if ($type eq "start")
              {
                &output ("\@var{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "ENV")
          {
            if ($type eq "start")
              {
                &output ("\@env{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "FILE")
          {
            if ($type eq "start")
              {
                &output ("\@file{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "COMMAND")
          {
            if ($type eq "start")
              {
                &output ("\@command{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "OPTION")
          {
            if ($type eq "start")
              {
                &output ("\@option{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "DFN")
          {
            if ($type eq "start")
              {
                &output ("\@dfn{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "CITE")
          {
            if ($type eq "start")
              {
                &output ("\@cite{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "ACRONYM")
          {
            if ($type eq "start")
              {
                &output ("\@acronym{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "URL")
          {
            if ($type eq "start")
              {
                &output ("\@url{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "EMPH")
          {
            if ($type eq "start")
              {
                &output ("\@emph{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "STRONG")
          {
            if ($type eq "start")
              {
                &output ("\@strong{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "SC")
          {
            if ($type eq "start")
              {
                &output ("\@sc{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "ROMAN")
          {
            if ($type eq "start")
              {
                &output ("\@r{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "ITALIC")
          {
            if ($type eq "start")
              {
                &output ("\@i{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "BOLD")
          {
            if ($type eq "start")
              {
                &output ("\@b{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "TYPEWRITER")
          {
            if ($type eq "start")
              {
                &output ("\@t{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "PRE")
          {
            if ($type eq "start")
              {
	        # Nothing to do;
              }
            else
              {
	        # Nothing to do;
              }
          }
        elsif ($element eq "EXDENT")
          {
            if ($type eq "start")
              {
                &output ("\@exdent ");
              }
            else
              {
                &output ("");
              }
          }
        elsif ($element eq "QUOTATION")
          {
            if ($type eq "start")
              {
                &output ("\n\@quotation");
              }
            else
              {
                &output ("\n\@end quotation\n");
              }
          }
        elsif ($element eq "DISPLAY")
          {
            if ($type eq "start")
              {
                &output ("\n\@display");
              }
            else
              {
                &output ("\n\@end display\n");
              }
          }
        elsif ($element eq "SMALLDISPLAY")
          {
            if ($type eq "start")
              {
                &output ("\n\@smalldisplay");
              }
            else
              {
                &output ("\n\@end smalldisplay\n");
              }
          }
        elsif ($element eq "EXAMPLE")
          {
            if ($type eq "start")
              {
                &output ("\n\@example\n");
              }
            else
              {
                &output ("\n\@end example\n");
              }
          }
        elsif ($element eq "SMALLEXAMPLE")
          {
            if ($type eq "start")
              {
                &output ("\n\@smallexample\n");
              }
            else
              {
                &output ("\n\@end smallexample\n");
              }
          }
        elsif ($element eq "FLUSHLEFT")
          {
            if ($type eq "start")
              {
                &output ("\n\@flushleft\n");
              }
            else
              {
                &output ("\n\@end flushleft\n");
              }
          }
        elsif ($element eq "FLUSHRIGHT")
          {
            if ($type eq "start")
              {
                &output ("\n\@flushright\n");
              }
            else
              {
                &output ("\n\@end flushright\n");
              }
          }
        elsif ($element eq "CENTER")
          {
            if ($type eq "start")
              {
                &output ("\n\@center ");
              }
            else
              {
                &output ("\n");
              }
          }
        elsif ($element eq "LISP")
          {
            if ($type eq "start")
              {
                &output ("\n\@lisp\n");
              }
            else
              {
                &output ("\n\@end lisp\n");
              }
          }
        elsif ($element eq "SMALLLISP")
          {
            if ($type eq "start")
              {
                &output ("\n\@smalllisp\n");
              }
            else
              {
                &output ("\n\@end smalllisp\n");
              }
          }
        elsif ($element eq "CARTOUCHE")
          {
            if ($type eq "start")
              {
                &output ("\n\@cartouche");
              }
            else
              {
                &output ("\n\@end cartouche\n");
              }
          }
        elsif ($element eq "FORMAT")
          {
            if ($type eq "start")
              {
                &output ("\n\@format\n");
              }
            else
              {
                &output ("\n\@end format\n");
              }
          }
        elsif ($element eq "SMALLFORMAT")
          {
            if ($type eq "start")
              {
                &output ("\n\@smallformat\n");
              }
            else
              {
                &output ("\n\@end smallformat\n");
              }
          }
        elsif ($element eq "TEXINFO")
          {
            # This element is a special in-line literal text.
            # There is nothing to do here.
            ;
          }
        elsif ($element eq "TEX")
          {
            if ($type eq "start")
              {
                &output ("\@tex\n");
              }
            else
              {
                &output ("\n\@end tex");
              }
          }
        elsif ($element eq "HTML")
          {
            if ($type eq "start")
              {
                &output ("\@html\n");
              }
            else
              {
                &output ("\n\@end html");
              }
          }
        elsif ($element eq "VERB")
          {
	    local ($char) = "";
            $char = ${$attributes}{'CHAR'};
            if ($type eq "start")
              {
                &output ("\@verb{$char");
              }
            else
              {
                &output ("$char}");
              }
          }
        elsif ($element eq "VERBATIM")
          {
            if ($type eq "start")
              {
                &output ("\n");
                &output ("\@verbatim");
                &output ("\n");
              }
            else
              {
                &output ("\n");
                &output ("\@end verbatim");
                &output ("\n");
              }
          }
        elsif ($element eq "VERBATIMINCLUDE")
          {
            if ($type eq "start")
              {
	        local ($file) = "";
                $file = ${$attributes}{'FILE'};

                &output ("\n");
                &output ("\@verbatiminclude $file");
                &output ("\n");
              }
            else
              {
		;
              }
          }
        elsif ($element eq "IFTEX")
          {
            if ($type eq "start")
              {
                &output ("\@iftex\n");
              }
            else
              {
                &output ("\n\@end iftex");
              }
          }
        elsif ($element eq "IFINFO")
          {
            if ($type eq "start")
              {
                &output ("\@ifinfo\n");
              }
            else
              {
                &output ("\n\@end ifinfo");
              }
          }
        elsif ($element eq "IFHTML")
          {
            if ($type eq "start")
              {
                &output ("\@ifhtml\n");
              }
            else
              {
                &output ("\n\@end ifhtml");
              }
          }
        elsif ($element eq "IFPLAINTEXT")
          {
            if ($type eq "start")
              {
                &output ("\@ifplaintext\n");
              }
            else
              {
                &output ("\n\@end ifplaintext");
              }
          }
        elsif ($element eq "IFXML")
          {
            if ($type eq "start")
              {
                &output ("\@ifxml\n");
              }
            else
              {
                &output ("\n\@end ifxml");
              }
          }
        elsif ($element eq "IFNOTTEX")
          {
            if ($type eq "start")
              {
                &output ("\@ifnottex\n");
              }
            else
              {
                &output ("\n\@end ifnottex");
              }
          }
        elsif ($element eq "IFNOTINFO")
          {
            if ($type eq "start")
              {
                &output ("\@ifnotinfo\n");
              }
            else
              {
                &output ("\n\@end ifnotinfo");
              }
          }
        elsif ($element eq "IFNOTHTML")
          {
            if ($type eq "start")
              {
                &output ("\@ifnothtml\n");
              }
            else
              {
                &output ("\n\@end ifnothtml");
              }
          }
        elsif ($element eq "IFNOTPLAINTEXT")
          {
            if ($type eq "start")
              {
                &output ("\@ifnotplaintext\n");
              }
            else
              {
                &output ("\n\@end ifnotplaintext");
              }
          }
        elsif ($element eq "IFNOTXML")
          {
            if ($type eq "start")
              {
                &output ("\@ifnotxml\n");
              }
            else
              {
                &output ("\n\@end ifnotxml");
              }
          }
        elsif ($element eq "IFTEXBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@iftex\n");
              }
            else
              {
                &output ("\n\@end iftex\n");
              }
          }
        elsif ($element eq "IFINFOBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifinfo\n");
              }
            else
              {
                &output ("\n\@end ifinfo\n");
              }
          }
        elsif ($element eq "IFHTMLBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifhtml\n");
              }
            else
              {
                &output ("\n\@end ifhtml\n");
              }
          }
        elsif ($element eq "IFPLAINTEXTBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifplaintext\n");
              }
            else
              {
                &output ("\n\@end ifplaintext\n");
              }
          }
        elsif ($element eq "IFXMLBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifxml\n");
              }
            else
              {
                &output ("\n\@end ifxml\n");
              }
          }
        elsif ($element eq "IFNOTTEXBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifnottex\n");
              }
            else
              {
                &output ("\n\@end ifnottex\n");
              }
          }
        elsif ($element eq "IFNOTINFOBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifnotinfo\n");
              }
            else
              {
                &output ("\n\@end ifnotinfo\n");
              }
          }
        elsif ($element eq "IFNOTHTMLBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifnothtml\n");
              }
            else
              {
                &output ("\n\@end ifnothtml\n");
              }
          }
        elsif ($element eq "IFNOTPLAINTEXTBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifnotplaintext\n");
              }
            else
              {
                &output ("\n\@end ifnotplaintext\n");
              }
          }
        elsif ($element eq "IFNOTXMLBLOCK")
          {
            if ($type eq "start")
              {
                &output ("\n\@ifnotxml\n");
              }
            else
              {
                &output ("\n\@end ifnotxml\n");
              }
          }
        elsif ($element eq "ITEMIZE")
          {
            if ($type eq "start")
              {
	        local ($mark) = "";
                $mark = ${$attributes}{'MARK'};
                &output ("\n\@itemize $mark");
              }
            else
              {
                &output ("\n\@end itemize\n");
              }
          }
        elsif ($element eq "ENUMERATE")
          {
            if ($type eq "start")
              {
	        local ($start) = "";
                $start = ${$attributes}{'START'};
                &output ("\n\@enumerate $start");
              }
            else
              {
                &output ("\n\@end enumerate\n");
              }
          }
        elsif ($element eq "TABLE")
          {
            if ($type eq "start")
              {
	        local ($emphasis) = "";
                $emphasis = lc ${$attributes}{'EMPHASIS'};
                &output ("\n\@table \@$emphasis");
              }
            else
              {
                &output ("\n\@end table\n");
              }
          }
        elsif ($element eq "VTABLE")
          {
            if ($type eq "start")
              {
	        local ($emphasis) = "";
                $emphasis = lc ${$attributes}{'EMPHASIS'};
                &output ("\n\@vtable \@$emphasis");
              }
            else
              {
                &output ("\n\@end vtable\n");
              }
          }
        elsif ($element eq "FTABLE")
          {
            if ($type eq "start")
              {
	        local ($emphasis) = "";
                $emphasis = lc ${$attributes}{'EMPHASIS'};
                &output ("\n\@ftable \@$emphasis");
              }
            else
              {
                &output ("\n\@end ftable\n");
              }
          }
        elsif ($element eq "ITEM")
          {
            if ($type eq "start")
              {
	        # Redirect output to a new stack level.
		&push_output ();
              }
            else
              {
	        local ($item) = "";
	        # Restore output.
                $item = pop_output ();
                &output ("\n\@item $item");
              }
          }
        elsif ($element eq "ITEMX")
          {
            if ($type eq "start")
              {
	        # Redirect output to a new stack level.
		&push_output ();
              }
            else
              {
	        local ($item) = "";
	        # Restore output.
                $item = pop_output ();
                &output ("\n\@itemx $item");
              }
          }
        elsif ($element eq "MULTITABLE")
          {
            if ($type eq "start")
              {
	        &output ("\n\@multitable");
                # Reset the $columnfractions global variable.
                $columnfractions = 0;
              }
            else
              {
                &output ("\n\@end multitable\n");
              }
          }
        elsif ($element eq "COLUMNFRACTION")
          {
            if ($type eq "start")
              {
	        # Redirect output to a new stack level.
		&push_output ();
              }
            else
              {
                local ($columnfraction) = "";
                # The column fraction value is recalled and saved.
                # The normal mode for output() function is re-established.
                $columnfraction = &pop_output ();
        
                if ($columnfractions)
		  {
           	    # We have already started a column fractions
		    # information line.
        	    &output (" $columnfraction");
        
                  }
		else
		  {
           	    # We start a column fractions information line.
          	    &output (" \@columnfractions $columnfraction");
           	    # We have to remember that.
        	    $columnfractions = 1;
                  }
              }
          }
        elsif ($element eq "COLUMNEXAMPLE")
          {
            if ($type eq "start")
              {
	        # Redirect output to a new stack level.
		&push_output ();
              }
            else
              {
                local ($columnexample) = "";
                # The column text example is recalled and saved.
                # The normal mode for output() function is re-established.
                $columnexample = pop_output;
                # Output the example text.
                &output (" \{$columnexample\}");
              }
          }
        elsif ($element eq "RAW")
          {
            if ($type eq "start")
              {
                &output ("\n\@item ");
              }
            else
              {
	        # Nothing to do;
		;
              }
          }
        elsif ($element eq "TAB")
          {
            if ($type eq "start")
              {
                &output ("\n\@tab ");
              }
            else
              {
	        # Nothing to do;
		;
              }
          }
        elsif ($element eq "DMN")
          {
            if ($type eq "start")
              {
                &output ("\@dmn{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "MATH")
          {
            if ($type eq "start")
              {
                &output ("\@math{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "FOOTNOTE")
          {
            if ($type eq "start")
              {
                &output ("\@footnote{");
              }
            else
              {
                &output ("}");
              }
          }
        elsif ($element eq "IMAGE")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                local ($width) = "";
                local ($height) = "";
                $name = ${$attributes}{'NAME'};
                $width = ${$attributes}{'WIDTH'};
                $height = ${$attributes}{'HEIGHT'};
                &output ("\n\@image\{ $name, $width, $height \}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "P")
          {
            if ($type eq "start")
              {
                local ($indent) = "";
                $indent = ${$attributes}{'INDENT'};
                if ($indent eq "ON")
                  {
        	    &output ("\n");
                  }
                else
                  {
        	    &output ("\n\@noindent\n");
                  }
              }
            else
              {
        	&output ("\n");
              }
          }
        elsif ($element eq "BR")
          {
            if ($type eq "start")
              {
                &output ("\@*");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DH")
          {
            if ($type eq "start")
              {
                &output ("\@-");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "HYPHENATION")
          {
            if ($type eq "start")
              {
                local ($words) = "";
                $words = ${$attributes}{'WORDS'};
                &output ("\n\@hyphenation\{$words\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SP")
          {
            if ($type eq "start")
              {
                local ($lines) = "";
                $lines = ${$attributes}{'LINES'};
                &output ("\n\@sp $lines\n");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "PAGE")
          {
            if ($type eq "start")
              {
                &output ("\n\@page\n");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "GROUP")
          {
            if ($type eq "start")
              {
                &output ("\n\@group");
              }
            else
              {
                &output ("\n\@end group\n");
              }
          }
        elsif ($element eq "NEED")
          {
            if ($type eq "start")
              {
                local ($mils) = "";
                $mils = ${$attributes}{'MILS'};
                &output ("\n\@need $mils\n");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "ARGS")
          {
            if ($type eq "start")
              {
                &output (" ");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFFN")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deffn \{$cat\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deffn\n");
              }
          }
        elsif ($element eq "DEFFNX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deffnx \{$cat\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFUN")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defun \{$name\}");
              }
            else
              {
                &output ("\n\@end defun\n");
              }
          }
        elsif ($element eq "DEFUNX")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defunx \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFMAC")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defmac \{$name\}");
              }
            else
              {
                &output ("\n\@end defmac\n");
              }
          }
        elsif ($element eq "DEFMACX")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defmacx \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFSPEC")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defspec \{$name\}");
              }
            else
              {
                &output ("\n\@end defspec\n");
              }
          }
        elsif ($element eq "DEFSPECX")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defspecx \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFVR")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defvr \{$cat\} \{$name\}");
              }
            else
              {
                &output ("\n\@end defvr\n");
              }
          }
        elsif ($element eq "DEFVRX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defvrx \{$cat\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFVAR")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defvar \{$name\}");
              }
            else
              {
                &output ("\n\@end defvar\n");
              }
          }
        elsif ($element eq "DEFVARX")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defvarx \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFOPT")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defopt \{$name\}");
              }
            else
              {
                &output ("\n\@end defopt\n");
              }
          }
        elsif ($element eq "DEFOPTX")
          {
            if ($type eq "start")
              {
                local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defoptx \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEFN")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypefn \{$cat\} \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypefn\n");
              }
          }
        elsif ($element eq "DEFTYPEFNX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypefnx \{$cat\} \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEFUN")
          {
            if ($type eq "start")
              {
                local ($type) = "";
                local ($name) = "";
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypefun \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypefun\n");
              }
          }
        elsif ($element eq "DEFTYPEFUNX")
          {
            if ($type eq "start")
              {
                local ($type) = "";
                local ($name) = "";
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypefunx \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEVR")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypevr \{$cat\} \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypevr\n");
              }
          }
        elsif ($element eq "DEFTYPEVRX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypevrx \{$cat\} \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEVAR")
          {
            if ($type eq "start")
              {
                local ($type) = "";
                local ($name) = "";
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypevar \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypevar\n");
              }
          }
        elsif ($element eq "DEFTYPEVARX")
          {
            if ($type eq "start")
              {
                local ($type) = "";
                local ($name) = "";
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypevarx \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFCV")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defcv \{$cat\} \{$class\} \{$name\}");
              }
            else
              {
                &output ("\n\@end defcv\n");
              }
          }
        elsif ($element eq "DEFCVX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defcvx \{$cat\} \{$class\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFIVAR")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defivar \{$class\} \{$name\}");
              }
            else
              {
                &output ("\n\@end defivar\n");
              }
          }
        elsif ($element eq "DEFIVARX")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defivarx \{$class\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEIVAR")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypeivar \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypeivar\n");
              }
          }
        elsif ($element eq "DEFTYPEIVARX")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypeivarx \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFOP")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defop \{$cat\} \{$class\} \{$name\}");
              }
            else
              {
                &output ("\n\@end defop\n");
              }
          }
        elsif ($element eq "DEFOPX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defopx \{$cat\} \{$class\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEOP")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypeop \{$cat\} \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypeop\n");
              }
          }
        elsif ($element eq "DEFTYPEOPX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypeopx \{$cat\} \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFMETHOD")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defmethod \{$class\} \{$name\}");
              }
            else
              {
                &output ("\n\@end defmethod\n");
              }
          }
        elsif ($element eq "DEFMETHODX")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@defmethodx \{$class\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTYPEMETHOD")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypemethod \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftypemethod\n");
              }
          }
        elsif ($element eq "DEFTYPEMETHODX")
          {
            if ($type eq "start")
              {
                local ($class) = "";
                local ($type) = "";
                local ($name) = "";
                $class = ${$attributes}{'CLASS'};
                $type = ${$attributes}{'TYPE'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftypemethodx \{$class\} \{$type\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFTP")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftp \{$cat\} \{$name\}");
              }
            else
              {
                &output ("\n\@end deftp\n");
              }
          }
        elsif ($element eq "DEFTPX")
          {
            if ($type eq "start")
              {
                local ($cat) = "";
                local ($name) = "";
                $cat = ${$attributes}{'CAT'};
                $name = ${$attributes}{'NAME'};
                &output ("\n\@deftpx \{$cat\} \{$name\}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
    }


    #-------------------------------------------------------------------
    # This is the elaboration process specific for the Sgmltexi DTD
    # that is translated into Texinfo.
    #
    # &sgml_tag_elab (TYPE,
    #                 ELEMENT,
    #                 %ATTRIBUTES,
    #                 TARGET,
    #                 ORIGINAL_NAME,
    #                 ROOT_FILE_NAME,
    #                 PAPER,
    #                 SETCHAPTERNEWPAGE,
    #                 FOOTNOTESTYLE,
    #                 HEADINGS,
    #                 OUTPUT_ENCODING)
    #
    sub sgml_tag_elab
    {
    
        #---------------------------------------------------------------
        # Function arguments.
        #---------------------------------------------------------------

        local ($type) = $_[0];
        local ($element) = $_[1];
        local ($attributes) = $_[2];
        local ($target) = $_[3];
        local ($original_file_name) = $_[4];
        local ($root_file_name) = $_[5];
        local ($paper) = $_[6];
        local ($setchapternewpage) = $_[7];
        local ($footnotestyle) = $_[8];
        local ($headings) = $_[9];
        local ($output_encoding) = $_[10];

        #---------------------------------------------------------------
        # Element handlers.
        # Element names and attribute names are uppercase.
        #---------------------------------------------------------------

        if ($element eq "SGMLTEXI")
          {
            if ($type eq "start")
              {
	        # Reset all counters.
                $intro = 0;
                $tome = 0;
                $part = 0;
                $chapter = 0;
                $appendix = 0;
                $sect1 = 0;         
                $sect2 = 0;         
                $sect3 = 0;         
                $index = 0;
                $unnumbered = 0;
                $menu_counter = 0;
                $current_level = "";
                $document_position = "";


                # Save the document language information.
                $documentlanguage = ${$attributes}{'LANG'};
    
		# Check if already fixed.
		if ($output_encoding eq "")
		  {
            	    $documentencoding = ${$attributes}{'CHARSET'};
		  }
		else
		  {
            	    $documentencoding = $output_encoding;
		  }
		
                $documentspacing = lc ${$attributes}{'SPACING'};
              }
            else
              {
                local ($n) = 0;

                # End of Texinfo source.
                &output ("\n\@bye");
              }
          }
        elsif ($element eq "HEAD")
          {
            if ($type eq "start")
              {
                # Save the document position.
                $document_position = "head";
              }
            else
              {
                # End of header: compose into Texinfo.
                local ($n) = 0;
                local ($text) = "";
        
                &output ("\\input texinfo  \@c -*-texinfo-*-");
                &output ("\n\@c %**start of header");
                &output ("\n\@setfilename $setfilename");
                &output ("\n\@settitle $settitle");
                if ($documentdescription ne "")
                  {
                    &output ("\n");
                    &output ("\@documentdescription");
                    &output ("\n");
                    &output ("$documentdescription");
                    &output ("\n");
                    &output ("\@end documentdescription");
                    &output ("\n");
                  }
                if ($setchapternewpage ne "")
                  {
                    &output ("\n\@setchapternewpage " . lc "$setchapternewpage");
                  }
                if ($footnotestyle ne "")
                  {
                    &output ("\n\@footnotestyle " . lc "$footnotestyle");
                  }
                if ($paper eq "")
                  {
                    &output ("\n\@c standard paper format");
                  }
                elsif ($paper eq "a4")
                  {
                    &output ("\n\@afourpaper");
                  }
                elsif ($paper eq "a4wide")
                  {
                    &output ("\n\@afourwide");
                  }
                elsif ($paper eq "a4latex")
                  {
                    &output ("\n\@afourlatex");
                  }
                elsif ($paper eq "a5")
                  {
                    &output ("\n\@afivepaper");
                  }
                elsif ($paper eq "small")
                  {
                    &output ("\n\@smallbook");
                  }
                # print @documentlanguage only if supplied.
                if ($documentlanguage ne "")
                  {
                    &output ("\n\@documentlanguage $documentlanguage");
                  }
                # print @documentencoding only if supplied.
                if ($documentencoding ne "")
                  {
                    &output ("\n\@documentencoding $documentencoding");
                  }
                # print @frenchspacing only if supplied.
                if ($documentspacing eq "french"
                    | $documentspacing eq "uniform")
                  {
                    &output ("\n\@frenchspacing");
                  }
                for ($n = 0 ; $n <= $#defcodeindex ; $n++)
                  { 
                    &output ("\n\@defcodeindex $defcodeindex[$n]");
                  }
                for ($n = 0 ; $n <= $#defindex ; $n++)
                  { 
                    &output ("\n\@defindex $defindex[$n]");
                  }
                for ($n = 0 ; $n <= $#syncodeindexfrom ; $n++)
                  { 
                    &output ("\n\@syncodeindex $syncodeindexfrom[$n] $syncodeindexto[$n]");
                  }
                for ($n = 0 ; $n <= $#synindexfrom ; $n++)
                  { 
                    &output ("\n\@synindex $synindexfrom[$n] $synindexto[$n]");
                  }
                &output ("\n\@finalout");
                &output ("\n\@c %**end of header");
                &output ("\n");
                &output ("\n\@comment This Texinfo source is generated automatically");
                &output ("\n\@comment with Sgmltexi, from an SGML source file.");
                &output ("\n\@comment Sgmltexi is available from:");
                &output ("\n\@comment http://master.swlibero.org/~daniele/software/sgmltexi/");
                &output ("\n");
                if ($infodir_category ne "")
                  {
                    # We have to add Info-dir informations.
                    &output ("\n");
                    &output ("\@dircategory $infodir_category\n");
                    &output ("\@direntry\n");
                    
                    # Do the "direntry" automatically or manually.
                    if ($infodir_contents eq "")
                      {
                        # Do it automatically.
                        $text = "* $settitle: (" . &root_name($setfilename, ".info") . ").";
                        if (length ($text) < 27)
                          {
                            # The space is ok
                            $text = $text . "                              ";
                            $text = substr ($text, 0, 27);
                          }
                        else
                          {
                            # The space is more as usual, so we
                            # don't worry about the indentation.
                            $text = $text . "  ";
                          }

                        output $text . $title . "\n";
                      }
                    else
                      {
                        # Do it manually.
                        output $infodir_contents;
                        &output ("\n");
                      }
                      
                    # Close "direntry".
                    &output ("\@end direntry\n");
                  }

                &output ("\n\@ifinfo");
                &output ("\n$abstract");
                &output ("\n");
                for ($n = 0 ; $n <= $#copyrights ; $n++)
                  { 
                    &output ("\n$copyrights[$n]\n");
                  }
                &output ("\n$license");
		# If there is something inside $legal, there is nothing
		# inside @copyrights and the others.
                &output ("\n$legal");
                &output ("\n\@end ifinfo");
                &output ("\n");
                &output ("\n\@titlepage");
                &output ("\n\@title $title");
                for ($n = 0 ; $n <= $#subtitles ; $n++)
                  { 
                    &output ("\n\@subtitle $subtitles[$n]");
                  }
                for ($n = 0 ; $n <= $#authors ; $n++)
                  { 
                    &output ("\n\@author $authors[$n]");
                  }
                &output ("\n$front_cover_text");
                &output ("\n\@page");
                &output ("\n$extra_after_cover");
                &output ("\n\@vskip 0pt plus 1filll");
                for ($n = 0 ; $n <= $#copyrights ; $n++)
                  { 
                    &output ("\n$copyrights[$n]\n");
                  }
                if ($publishnote ne "")
                  {
                    &output ("\n$publishnote");
                  }
                &output ("\n$license");
                if ($coverart ne "")
                  {
                    &output ("\n\@sp 2");
                    &output ("\n$coverart");
                  }
		# If there is something inside $legal, there is nothing
		# inside @copyrights and the others.
                &output ("\n$legal");

                &output ("\n$extra_after_legal");
                if ($dedications ne "")
                  {
                    &output ("\n\@iftex");
                    &output ("\n\@page");
                    &output ("\n$dedications");
                    &output ("\n\@end iftex");
                  }
                if ($extra_after_dedications ne "")
                  {
                    &output ("\n\@page");
                    &output ("\n$extra_after_dedications");
                  }
                &output ("\n\@end titlepage");
                if ($headings ne "")
                  {
                    # It is necessary an extra empty line before,
                    # otherwise it happens something strange.
                    &output ("\n");
                    &output ("\n\@headings " . lc "$headings");
                  }
                if ($summarycontents)
                  {
                    &output ("\n");
                    &output ("\n\@summarycontents");
                  }
                if ($shortcontents)
                  {
                    &output ("\n");
                    &output ("\n\@shortcontents");
                  }
                if ($contents)
                  {
                    &output ("\n");
                    &output ("\n\@contents");
                  }
                &output ("\n");
                &output ("\n\@ifnottex");
                &output ("\n\@node Top, "
                         . $top_node_next
                         . ", "
                         . $top_node_previous
                         . ", "
                         . $top_node_up);
                &output ("\n\@top $settitle");
                &output ("\n");
                &output ("\n$abstract");
                &output ("\n");

		# Transfer data contained inside $info_auto_menus{NODE}
                &output ("\n");
                &output ("\@menu\n");
                if ($info_manual_menus{$list_info_menu[0]} =~ m/^[^a-z0-9]*$/is)
		  {
                    # The manual menu is empty. Use auto.
                    &output ($info_auto_menus{$list_info_menu[0]});
                  }
                else
                  {
                    # The manual menu is present. Use it.
                    &output ($info_manual_menus{$list_info_menu[0]});
                  }
                &output ("\@end menu\n");
                &output ("\@end ifnottex\n");
              }
          }
        elsif ($element eq "ADMIN")
          {
            # Nothing to do.
            ;
          }
        elsif ($element eq "SETFILENAME")
          {
            if ($type eq "start")
              {
                # Save the information.
                $setfilename = ${$attributes}{'CONTENT'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SETTITLE")
          {
            if ($type eq "start")
              {
                # Save the information.
                $settitle = ${$attributes}{'CONTENT'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DOCUMENTDESCRIPTION")
          {
            if ($type eq "start")
              {
                # Save the information.
                $documentdescription = ${$attributes}{'CONTENT'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SETCHAPTERNEWPAGE")
          {
            if ($type eq "start")
              {
                # check if this information is overridden:
                if ($setchapternewpage eq "")
                  {
                    # The information is not overridden:
                    # save the information.
                    $setchapternewpage = ${$attributes}{'CONTENT'};
                  }
                else
                  {
                    # Don't change anything.
                    ;
                  }
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "FOOTNOTESTYLE")
          {
            if ($type eq "start")
              {
                # check if this information is overridden:
                if ($footnotestyle eq "")
                  {
                    # The information is not overridden:
                    # save the information.
                    $footnotestyle = ${$attributes}{'CONTENT'};
                  }
                else
                  {
                    # Don't change anything.
                    ;
                  }
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "HEADINGS")
          {
            if ($type eq "start")
              {
                # check if this information is overridden:
                if ($headings eq "")
                  {
                    # The information is not overridden:
                    # save the information.
                    $headings = ${$attributes}{'CONTENT'};
                  }
                else
                  {
                    # Don't change anything.
                    ;
                  }
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SYNCODEINDEX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $syncodeindexfrom[$#syncodeindexfrom+1]
                  = ${$attributes}{'FROM'};
                $syncodeindexto[$#syncodeindexto+1]
                  = ${$attributes}{'TO'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SYNINDEX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $synindexfrom[$#synindexfrom+1]
                  = ${$attributes}{'FROM'};
                $synindexto[$#synindexto+1]
                  = ${$attributes}{'TO'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFCODEINDEX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $defcodeindex[$#defcodeindex+1] = ${$attributes}{'NAME'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "DEFINDEX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $defindex[$#defindex+1] = ${$attributes}{'NAME'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "INFODIR")
          {
            if ($type eq "start")
              {
                # Save the information.
                $infodir_category =  ${$attributes}{'CAT'};
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output (if any).
                $infodir_contents = &pop_output ();
              }
          }
        elsif ($element eq "TITLEPAGE")
          {
            # Nothing to do.
            ;
          }
        elsif ($element eq "TITLE")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
                # Remember that the front cover is started.
                $tp_current_position = "cover";
              }
            else
              {
                # Recall output.
                $title = &pop_output ();
              }
          }
        elsif ($element eq "SUBTITLE")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $subtitles[$#subtitles+1] = &pop_output ();
              }
          }
        elsif ($element eq "ABSTRACT")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $abstract = &pop_output ();

                # With %block; elements, there is a line feed character
                # at the top of the string. I don't know why.
                # Anyway, we have to delete this extra line feed.
                $abstract =~ s/^\n?(.*)$/$1/s;
              }
          }
        elsif ($element eq "AUTHOR")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $authors[$#authors+1] = &pop_output ();
              }
          }
        elsif ($element eq "FRONTCOVERTEXT")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $front_cover_text = &pop_output ();
              }
          }
        elsif ($element eq "TPEXTRA")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                if ($tp_current_position eq "cover")
                  {
                    $extra_after_cover = &pop_output ();
                  }
                elsif ($tp_current_position eq "legal")
                  {
                    $extra_after_legal = &pop_output ();
                  }
                elsif ($tp_current_position eq "dedications")
                  {
                    $extra_after_dedications = &pop_output ();
                  }
              }
          }
        elsif ($element eq "LEGAL")
          {
            if ($type eq "start")
              {
        	# Remember that the legal information is started.
        	$tp_current_position = "legal";
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $legal = &pop_output ();
              }
          }
        elsif ($element eq "COPYRIGHT")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $copyrights[$#copyrights+1] = &pop_output ();
              }
          }
        elsif ($element eq "PUBLISHNOTE")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $publishnote = &pop_output ();

                # With %block; elements, there is a line feed character
                # at the top of the string. I don't know why.
                # Anyway, we have to delete this extra line feed.
                $publishnote =~ s/^\n?(.*)$/$1/s;
              }
          }
        elsif ($element eq "LICENSE")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $license = &pop_output ();

                # With %block; elements, there is a line feed character
                # at the top of the string. I don't know why.
                # Anyway, we have to delete this extra line feed.
                $license =~ s/^\n?(.*)$/$1/s;
              }
          }
        elsif ($element eq "COVERART")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
              }
            else
              {
                # Recall output.
                $coverart = &pop_output ();

                # With %block; elements, there is a line feed character
                # at the top of the string. I don't know why.
                # Anyway, we have to delete this extra line feed.
                $coverart =~ s/^\n?(.*)$/$1/s;
              }
          }
        elsif ($element eq "DEDICATIONS")
          {
            if ($type eq "start")
              {
                # Save output.
                &push_output ();
                # Remember that the dedication information is started.
                $tp_current_position = "dedications";
              }
            else
              {
                # Recall output.
                $dedications = &pop_output ();
              }
          }
        elsif ($element eq "CONTENTS")
          {
            if ($type eq "start")
              {
                # Save the information.
                $contents = 1;
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SHORTCONTENTS")
          {
            if ($type eq "start")
              {
                # Save the information.
                $shortcontents = 1;
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "SUMMARYCONTENTS")
          {
            if ($type eq "start")
              {
                # Save the information.
                $summarycontents = 1;
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "TOPNODE")
          {
            if ($type eq "start")
              {
                # Save top node information.
                $top_node_next = ${$attributes}{'NEXT'};
                $top_node_previous = ${$attributes}{'PREV'};
                $top_node_up = ${$attributes}{'UP'};
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "MENU")
          {
            if ($type eq "start")
              {
	        # Insert a new menu here.
	        $menu_counter++;

                # Save output.
                &push_output ();
              }
            else
              {
		# Eliminate output (it was elaborated with the first pass).
		&pop_output ();

                # Transfer data contained inside $info_auto_menus{NODE}
                &output ("\n");
                &output ("\@ifnottex\n");
                &output ("\@menu\n");
                if ($info_manual_menus{$list_info_menu[$menu_counter]} =~ m/^[^a-z0-9]*$/is)
                  {
                    # The manual menu is empty. Use auto.
                    &output ($info_auto_menus{$list_info_menu[$menu_counter]});
                  }
                else
                  {
                    # The manual menu is present. Use it.
                    &output ($info_manual_menus{$list_info_menu[$menu_counter]});
                  }
                &output ("\@end menu\n");
                &output ("\@end ifnottex\n");
		
		# Remember the current menu level to be able to
		# print @menu commands before sections.
                if ($current_level eq "tome")
                  {
                    $info_menu_levels[1] = 1;
                  }
                elsif ($current_level eq "part")
                  {
                    $info_menu_levels[2] = 1;
                  }
                elsif ($current_level eq "chapter-h1"
                       || $current_level eq "chapter-u-h1"
                       || $current_level eq "intro-h1"
                       || $current_level eq "appendix-h1"
                       || $current_level eq "appendix-u-h1"
                       || $current_level eq "index")
                  {
                    $info_menu_levels[3] = 1;
                  }
                elsif ($current_level eq "chapter-h2"
                       || $current_level eq "chapter-u-h2"
                       || $current_level eq "intro-h2"
                       || $current_level eq "appendix-h2"
                       || $current_level eq "appendix-u-h2")
                  {
                    $info_menu_levels[4] = 1;
                  }
                elsif ($current_level eq "chapter-h3"
                       || $current_level eq "chapter-u-h3"
                       || $current_level eq "intro-h3"
                       || $current_level eq "appendix-h3"
                       || $current_level eq "appendix-u-h3")
                  {
                    $info_menu_levels[5] = 1;
                  }
              }
          }
        elsif ($element eq "INTRO")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "intro";
              }
            else
              {
	        # Nothing to do.
		;
              }
          }
        elsif ($element eq "BODY")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "body";
              }
            else
              {
	        # Nothing to do.
		;
              }
          }
        elsif ($element eq "APPENDIX")
          {
            if ($type eq "start")
              {
                # Save the information.
                $document_position = "appendix";
              }
            else
              {
	        # Nothing to do.
		;
              }
          }
        elsif ($element eq "TOMEHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $tome_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $tome_heading_node = ${$attributes}{'NODE'};
                $tome_heading_menu = ${$attributes}{'MENU'};
                $tome_heading_next = ${$attributes}{'NEXT'};
                $tome_heading_prev = ${$attributes}{'PREV'};
                $tome_heading_up   = ${$attributes}{'UP'};
                # Here start a tome. Do some preparations.
                # Tome happens only inside a body.
                $current_level = "tome";
                $tome++;
                # part counter doesn't change.
                # chapter counter doesn't change.
                $sect1 = 0;		
                $sect2 = 0;		
                $sect3 = 0;		

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                  }
                if ( $info_menu_levels[2] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[2] = 0;
                  }
                if ( $info_menu_levels[1] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[1] = 0;
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $tome_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($tome_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $tome_heading_node = &short_level_description;
                  }
                
                # The node and header is actually typeset.
                &output ("\n\@c ************************************************");
                &output ("*********************");
                &output ("\n\@c TOME");
                &output ("\n\@c ************************************************");
                &output ("*********************");
                &output ("\n\@node $tome_heading_node");
		if ($tome_heading_next eq ""
		    && $tome_heading_prev eq ""
		    && $tome_heading_up eq "")
		  {
		    # Here is no node sequence information.
		    ;
		  }
		else
		  {
		    # Node sequence information must be added.
		    &output (", $tome_heading_next, $tome_heading_prev, $tome_heading_up");
		  }
                &output ("\n\@unnumbered ");
                output ucfirst &tome_def . " " . &integer_to_roman($tome);
                &output (" - $tome_heading_title");
               if ($tome_heading_anchor ne "")
                 {
        	   &output ("\n\@anchor{$tome_heading_anchor}");
                 }
              }
          }
        elsif ($element eq "PARTHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $part_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $part_heading_node = ${$attributes}{'NODE'};
                $part_heading_menu = ${$attributes}{'MENU'};
                $part_heading_next = ${$attributes}{'NEXT'};
                $part_heading_prev = ${$attributes}{'PREV'};
                $part_heading_up   = ${$attributes}{'UP'};
                # Here start a part. Do some preparations.
                # Tome happens only inside a body.
                $current_level = "part";
                $part++;
                # chapter counter doesn't change.
                $sect1 = 0;		
                $sect2 = 0;		
                $sect3 = 0;		

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                  }
                if ( $info_menu_levels[2] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[2] = 0;
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $part_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($part_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $part_heading_node = &short_level_description;
                  }

                # The node and header is actually typeset.
                &output ("\n\@c ================================================");
                &output ("====================");
                &output ("\n\@c PART");
                &output ("\n\@c ================================================");
                &output ("=====================");
                &output ("\n\@node $part_heading_node");
		if ($part_heading_next eq ""
		    && $part_heading_prev eq ""
		    && $part_heading_up eq "")
		  {
		    # Here is no node sequence information.
		    ;
		  }
		else
		  {
		    # Node sequence information must be added.
		    &output (", $part_heading_next, $part_heading_prev, $part_heading_up");
		  }
                &output ("\n\@unnumbered ");
                output ucfirst &part_def . " " . &integer_to_roman($part);
                &output (" - $part_heading_title");
                if ($part_heading_anchor ne "")
                  {
          	    &output ("\n\@anchor{$part_heading_anchor}");
                  }
              }
          }
        elsif ($element eq "H1")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h1_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h1_node = ${$attributes}{'NODE'};
                $h1_menu = ${$attributes}{'MENU'};
                $h1_next = ${$attributes}{'NEXT'};
                $h1_prev = ${$attributes}{'PREV'};
                $h1_up   = ${$attributes}{'UP'};
                $h1_type = lc ${$attributes}{'TYPE'};
                # Here start a chapter. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h1";
        	    $intro++;
        	    $sect1 = 0;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h1_type eq "unnumbered"
                        || $h1_type eq "heading")
                      {
        	        $current_level = "chapter-u-h1";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h1";
        	        $chapter++;
                      }

        	    $sect1 = 0;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h1_type eq "unnumbered"
                        || $h1_type eq "heading")
                      {
        	        $current_level = "appendix-u-h1";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h1";
        	        $appendix++;
                      }

        	    $sect1 = 0;
        	    $sect2 = 0;
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }
                if ( $info_menu_levels[3] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[3] = 0;
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h1_title = &pop_output ();

                # Check if the node name is required.
                if ($h1_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $h1_node = &short_level_description;
                  }

                # The node and header is actually typeset.
                &output ("\n\@c ------------------------------------------------");
                &output ("---------------------");
                &output ("\n\@c CHAPTER");
                &output ("\n\@c ------------------------------------------------");
                &output ("---------------------");
                &output ("\n\@node $h1_node");
		if ($h1_next eq ""
		    && $h1_prev eq ""
		    && $h1_up eq "")
		  {
		    # Here is no node sequence information.
		    ;
		  }
		else
		  {
		    # Node sequence information must be added.
		    &output (", $h1_next, $h1_prev, $h1_up");
		  }
                if ($document_position eq "intro"
                    || $h1_type eq "unnumbered")
                  {
                    &output ("\n\@unnumbered $h1_title");
                  }
                elsif ($h1_type eq "heading")
                  {
                    &output ("\n\@chapheading $h1_title");
                  }
                elsif ($document_position eq "body")
                  {
                    &output ("\n\@chapter $h1_title");
                  }
                elsif ($document_position eq "appendix")
                  {
                    &output ("\n\@appendix $h1_title");
                  }
                if ($h1_anchor ne "" )
                  {
        	    &output ("\n\@anchor{$h1_anchor}");
                  }
              }
          }
        elsif ($element eq "H2")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h2_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h2_node = ${$attributes}{'NODE'};
                $h2_menu = ${$attributes}{'MENU'};
                $h2_next = ${$attributes}{'NEXT'};
                $h2_prev = ${$attributes}{'PREV'};
                $h2_up   = ${$attributes}{'UP'};
                $h2_type = lc ${$attributes}{'TYPE'};
                # Here start a section. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h2";
        	    $sect1++;		
        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h2_type eq "unnumbered"
                        || $h2_type eq "heading")
                      {
        	        $current_level = "chapter-u-h2";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h2";
                 	$sect1++;
                      }

        	    $sect2 = 0;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h2_type eq "unnumbered"
                        || $h2_type eq "heading")
                      {
        	        $current_level = "appendix-u-h2";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h2";
        	        $sect1++;
                      }

        	    $sect2 = 0;
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }
                if ( $info_menu_levels[4] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[4] = 0;
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h2_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[3])
                  {
                    if ($h2_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h2_node = &short_level_description;
                      }

                    # Print the node name.
	            &output ("\n\@node $h2_node");
		    if ($h2_next eq ""
		        && $h2_prev eq ""
			&& $h2_up eq "")
		      {
		        # Here is no node sequence information.
		        ;
	              }
		    else
		      {
		        # Node sequence information must be added.
		        &output (", $h2_next, $h2_prev, $h2_up");
		      }
		  }
                # The header is actually typeset.
                if ($document_position eq "intro"
                    || $h2_type eq "unnumbered")
                  {
                    &output ("\n\@unnumberedsec $h2_title");
                  }
                elsif ($h2_type eq "heading")
                  {
                    &output ("\n\@heading $h2_title");
                  }
                elsif ($document_position eq "body")
                  {
                    &output ("\n\@section $h2_title");
                  }
                elsif ($document_position eq "appendix")
                  {
                    &output ("\n\@appendixsec $h2_title");
                  }
                if ($h2_anchor ne "")
                  {
        	    &output ("\n\@anchor{$h2_anchor}");
                  }
              }
          }
        elsif ($element eq "H3")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h3_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h3_node = ${$attributes}{'NODE'};
                $h3_menu = ${$attributes}{'MENU'};
                $h3_next = ${$attributes}{'NEXT'};
                $h3_prev = ${$attributes}{'PREV'};
                $h3_up   = ${$attributes}{'UP'};
                $h3_type = lc ${$attributes}{'TYPE'};
                # Here start a subsection. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h3";
        	    $sect2++;		
        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h3_type eq "unnumbered"
                        || $h3_type eq "heading")
                      {
        	        $current_level = "chapter-u-h3";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h3";
        	        $sect2++;		
                      }

        	    $sect3 = 0;		
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h3_type eq "unnumbered"
                        || $h3_type eq "heading")
                      {
        	        $current_level = "appendix-u-h3";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h3";
        	        $sect2++;
                      }
        	    $sect3 = 0;
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # Arrange Info menu levels
                #@info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                if ( $info_menu_levels[5] )
                  {
                    # We must reset it to zero and close the menu.
                    $info_menu_levels[5] = 0;
                  }

                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h3_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[4])
                  {
                    if ($h3_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h3_node = &short_level_description;
                      }
                    # Print the node name.
	            &output ("\n\@node $h3_node");
		    if ($h3_next eq ""
		        && $h3_prev eq ""
			&& $h3_up eq "")
		      {
		        # Here is no node sequence information.
		        ;
	              }
		    else
		      {
		        # Node sequence information must be added.
		        &output (", $h3_next, $h3_prev, $h3_up");
		      }
                  }

                # The header is actually typeset.
                if ($document_position eq "intro"
                    || $h3_type eq "unnumbered")
                  {
                    &output ("\n\@unnumberedsubsec $h3_title");
                  }
                elsif ($h3_type eq "heading")
                  {
                    &output ("\n\@subheading $h3_title");
                  }
                elsif ($document_position eq "body")
                  {
                    &output ("\n\@subsection $h3_title");
                  }
                elsif ($document_position eq "appendix")
                  {
                    &output ("\n\@appendixsubsec $h3_title");
                  }
                if ($h3_anchor ne "")
                  {
        	    &output ("\n\@anchor{$h3_anchor}");
                  }
              }
          }
        elsif ($element eq "H4")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $h4_anchor = ${$attributes}{'ID'};
                # Save node information.
                $h4_node = ${$attributes}{'NODE'};
                $h4_menu = ${$attributes}{'MENU'};
                $h4_next = ${$attributes}{'NEXT'};
                $h4_prev = ${$attributes}{'PREV'};
                $h4_up   = ${$attributes}{'UP'};
                $h4_type = lc ${$attributes}{'TYPE'};
                # Here start a sub-subsection. Do some preparations.
                if ($document_position eq "intro")
                  {
        	    $current_level = "intro-h4";
        	    $sect3++;		
                  }
                elsif ($document_position eq "body")
                  {
                    if ($h4_type eq "unnumbered"
                        || $h4_type eq "heading")
                      {
        	        $current_level = "chapter-u-h4";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "chapter-h4";
        	        $sect3++;		
                      }
                  }
                elsif ($document_position eq "appendix")
                  {
                    if ($h4_type eq "unnumbered"
                        || $h4_type eq "heading")
                      {
        	        $current_level = "appendix-u-h4";
        	        $unnumbered++;
                      }
                    else
                      {
        	        $current_level = "appendix-h4";
        	        $sect3++;
                      }
                  }

                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $h4_title = &pop_output ();

                # Do we have to add the node?
                # @info_menu_levels = (TOP, TOME, PART, H1, H2, H3)
                #
                # Check if the node name is required.
                # This happens if the previous head level include
                # an Info menu.
                #
                if ($info_menu_levels[5])
                  {
                    if ($h4_node eq "")
                      {
                        # Define a short description useful as node-name.
                        $h4_node = &short_level_description;
                      }
                    # Print the node name.
	            &output ("\n\@node $h4_node");
		    if ($h4_next eq ""
		        && $h4_prev eq ""
			&& $h4_up eq "")
		      {
		        # Here is no node sequence information.
		        ;
	              }
		    else
		      {
		        # Node sequence information must be added.
		        &output (", $h4_next, $h4_prev, $h4_up");
		      }
                  }

                # The header is actually typeset.
                if ($document_position eq "intro"
                    || $h4_type eq "unnumbered")
                  {
                    &output ("\n\@unnumberedsubsubsec $h4_title");
                  }
                elsif ($h4_type eq "heading")
                  {
                    &output ("\n\@subsubheading $h4_title");
                  }
                elsif ($document_position eq "body")
                  {
                    &output ("\n\@subsubsection $h4_title");
                  }
                elsif ($document_position eq "appendix")
                  {
                    &output ("\n\@appendixsubsubsec $h4_title");
                  }
                if ($h4_anchor ne "")
                  {
        	    &output ("\n\@anchor{$h4_anchor}");
                  }
              }
          }
        elsif ($element eq "INDEXHEADING")
          {
            if ($type eq "start")
              {
                # Save anchor information.
                $index_heading_anchor = ${$attributes}{'ID'};
                # Save node information.
                $index_heading_node = ${$attributes}{'NODE'};
                $index_heading_menu = ${$attributes}{'MENU'};
                $index_heading_next = ${$attributes}{'NEXT'};
                $index_heading_prev = ${$attributes}{'PREV'};
                $index_heading_up   = ${$attributes}{'UP'};

                # Here start an index. Do some preparations.
        	$current_level = "index";
        	$index++;
                # Send the output stream to a new stack level.        
                &push_output ();
              }
            else
              {
                # The header information is recalled and saved.
                # The normal mode for output() function is re-established.
                $index_heading_title = &pop_output ();

                # Check if the node name is required.
                if ($index_heading_node eq "")
                  {
                    # Define a short description useful as node-name.
                    $index_heading_node = &short_level_description;
                  }

                # The node and header is actually typeset.
                &output ("\n\@c ------------------------------------------------");
                &output ("---------------------");
                &output ("\n\@c INDEX");
                &output ("\n\@c ------------------------------------------------");
                &output ("---------------------");
                &output ("\n\@node $index_heading_node");

		if ($index_heading_next eq ""
		    && $index_heading_prev eq ""
		    && $index_heading_up eq "")
		  {
		    # Here is no node sequence information.
		    ;
		  }
		else
		  {
		    # Node sequence information must be added.
		    &output (", $index_heading_next, $index_heading_prev, $index_heading_up");
		  }

                &output ("\n\@unnumbered $index_heading_title");
                if ($index_heading_anchor ne "")
		  {
        	    &output ("\n\@anchor{$index_heading_anchor}");
                  }
              }
          }
        elsif ($element eq "PRINTINDEX")
          {
            if ($type eq "start")
              {
		local ($name) = "";
                $name = ${$attributes}{'NAME'};
                &output ("\n");
                &output ("\n\@printindex $name");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "CINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@cindex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "FINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@findex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "VINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@vindex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "KINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@kindex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "PINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@pindex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "TINDEX")
          {
            if ($type eq "start")
              {
		local ($entry) = "";
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@tindex $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "USERINDEX")
          {
            if ($type eq "start")
              {
		local ($name) = "";
		local ($entry) = "";
                $name = ${$attributes}{'NAME'};
                $entry = ${$attributes}{'ENTRY'};
                &output ("\n\@" . "$name" . "index $entry");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "ANCHOR")
          {
            if ($type eq "start")
              {
		local ($id) = "";
                $id = ${$attributes}{'ID'};
                &output ("\@anchor{$id}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "XREF")
          {
            if ($type eq "start")
              {
		local ($id) = "";
                local ($name) = "";
                local ($title) = "";
                local ($info) = "";
                local ($ptitle) = "";
                $id = ${$attributes}{'ID'};
                $name = ${$attributes}{'NAME'};
                $title = ${$attributes}{'TITLE'};
                $info = ${$attributes}{'INFO'};
                $ptitle = ${$attributes}{'PTITLE'};
                &output ("\@xref{$id,$name,$title,$info,$ptitle}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "REF")
          {
            if ($type eq "start")
              {
		local ($id) = "";
                local ($name) = "";
                local ($title) = "";
                local ($info) = "";
                local ($ptitle) = "";
                $id = ${$attributes}{'ID'};
                $name = ${$attributes}{'NAME'};
                $title = ${$attributes}{'TITLE'};
                $info = ${$attributes}{'INFO'};
                $ptitle = ${$attributes}{'PTITLE'};
                &output ("\@ref{$id,$name,$title,$info,$ptitle}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "PXREF")
          {
            if ($type eq "start")
              {
		local ($id) = "";
                local ($name) = "";
                local ($title) = "";
                local ($info) = "";
                local ($ptitle) = "";
                $id = ${$attributes}{'ID'};
                $name = ${$attributes}{'NAME'};
                $title = ${$attributes}{'TITLE'};
                $info = ${$attributes}{'INFO'};
                $ptitle = ${$attributes}{'PTITLE'};
                &output ("\@pxref{$id,$name,$title,$info,$ptitle}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "INFOREF")
          {
            if ($type eq "start")
              {
		local ($id) = "";
                local ($name) = "";
                local ($info) = "";
                $id = ${$attributes}{'ID'};
                $name = ${$attributes}{'NAME'};
                $info = ${$attributes}{'INFO'};
                &output ("\@inforef{$id,$name,$info}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "UREF")
          {
            if ($type eq "start")
              {
		local ($uri) = "";
                local ($name) = "";
                local ($replace) = "";
                $uri = ${$attributes}{'URI'};
                $name = ${$attributes}{'NAME'};
                $replace = ${$attributes}{'REPLACE'};
                if ($name eq "" && $replace eq "")
		  {
        	    &output ("\@uref{$uri}");
                  }
		else
		  {
                    &output ("\@uref{$uri,$name,$replace}");
                  }
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
        elsif ($element eq "EMAIL")
          {
            if ($type eq "start")
              {
		local ($email) = "";
                local ($name) = "";
                $email = ${$attributes}{'EMAIL'};
                $name = ${$attributes}{'NAME'};
                &output ("\@email{$email,$name}");
              }
            else
              {
                # Nothing to do.
                ;
              }
          }
	else
	  {
	    &sgml_tag_elab_basic
		($type,
		 $element,
		 $attributes,
                 $target,
		 $original_file_name,
                 $root_file_name,
		 $paper,
                 $setchapternewpage,
                 $footnotestyle,
                 $headings,
		 $output_encoding);
	  }

    } # sgml_tag_elab

    #-------------------------------------------------------------------
    # Start.
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # First scan.
    #-------------------------------------------------------------------

    # Output from output() is sent to /dev/null
    $current_output_stream = "/dev/null";
    open ($current_output_stream, "> /dev/null");

    # Open input file.
    open ($input_stream, "< $input_file");

    &diag_output (sprintf (gettext ("%s:%s scanning post-SP searching for cross references.\n"),
                           $program_executable, $original_file_name));

    # Scan the post-SP output.
    while ($line = <$input_stream>)
      {
        # Determinate what kind of SP record is.
        if ($line =~ m/^A([a-z]*) ([a-z]*) ?(.*)$/i)
          {
            # This is an attribute record: $1 is the attribute name;
            # $2 is the attribute type; $3 is the attribute value.
            # We save the name and the value.
            %element_attribute = (%element_attribute, "$1", "$3");
          }
        elsif ($line =~ m/^\((.*)$/i)
          {
            # This is an element start: $1.
            &sgml_tag_elab_first_pass
		("start", $1, \%element_attribute,
                 $target,
		 $original_file_name,
                 $root_file_name,
		 $paper,
                 $setchapternewpage,
                 $footnotestyle,
                 $headings,
		 $output_encoding);
          }
        elsif ($line =~ m/^\)(.*)$/i)
          {
            # This is an element end: $1.
            &sgml_tag_elab_first_pass
		("end", $1, \%element_attribute,
                 $target,
		 $original_file_name,
                 $root_file_name,
		 $paper,
                 $setchapternewpage,
                 $footnotestyle,
                 $headings,
		 $output_encoding);

            # Reset %element_attribute associative array.
            %element_attribute = ();
          }
        elsif ($line =~ m/^\-(.*)$/i)
          {
            # This is parsed character text: $1.
            $pcdata = $1;

            # This text must be transformed if necessary.
	    #
	    # Notice that the \\ to \bsol translation and back is just
	    # an hack to resolve this problem inside SP records.
	    #
	    # Suppose we have:
	    #	bla bla bla \\no bla bla bla.
	    # If we translate the two \\ into a single \, we will have
	    #	bla bla bla \no bla bla bla.
	    # and then we will have a new line there. If the check
	    # the new line before, we will have
	    #	bla bla bla \
            #   o bla bla bla.
	    # with a residual \.
	    # But we wanted exactly.
	    #	bla bla bla \no bla bla bla.
	    # 
            $pcdata =~ s/\\\|//g;                 # \|            --> "" (SDATA residual delimiters)
            $pcdata =~ s/\\\\/\\bsol/g;           # \\            --> \bsol
            $pcdata =~ s/\\n/\n/g;                # \n            --> new line
            $pcdata =~ s/\\bsol/\\/g;             # \bsol         --> \
            
            # The text is released.
            &output ($pcdata);
          }
        elsif ($line =~ m/^\C$/i)
          {
            # The file is OK.
            # Nothing to do.
            ;
          }
        else
          {
            # This is an unknown record type.
            printf STDERR (gettext ("%s: unknown post-SP record: %s"),
                           $program_executable, $line);
          }

      } # while

    # Close input file.
    close ($input_stream);

    # Close output stream and reset @output_stack.
    close ($current_output_stream);
    @output_stack = ();


    #-------------------------------------------------------------------
    # Second scan.
    #-------------------------------------------------------------------

    # A Texinfo source file is started.
    $current_output_stream = $root_file_name . ".texinfo";
    open ($current_output_stream, "> $root_file_name.texinfo");

    # Open input file.
    open ($input_stream, "< $input_file");

    &diag_output (sprintf (gettext ("%s:%s scanning post-SP again for typesetting.\n"),
                           $program_executable, $original_file_name));

    # Scan the post-SP output.
    while ( $line = <$input_stream> )
      {

        # Determinate what kind of SP record is.
        if ( $line =~ m/^A([a-z]*) ([a-z]*) ?(.*)$/i )
          {
            # This is an attribute record: $1 is the attribute name;
            # $2 is the attribute type; $3 is the attribute value.
            # We save the name and the value.
            %element_attribute = (%element_attribute, "$1", "$3");
          }
        elsif ( $line =~ m/^\((.*)$/i )
          {

            # This is an element start: $1.
            &sgml_tag_elab ("start", $1, \%element_attribute,
                            $target, $original_file_name,
                            $root_file_name, $paper,
                            $setchapternewpage,
                            $footnotestyle,
                            $headings,
			    $output_encoding);
          }
        elsif ( $line =~ m/^\)(.*)$/i )
          {
            # This is an element end: $1.
            &sgml_tag_elab ("end", $1, \%element_attribute,
                            $target, $original_file_name,
                            $root_file_name, $paper,
                            $setchapternewpage,
                            $footnotestyle,
                            $headings,
			    $output_encoding);

            # Reset %element_attribute associative array.
            %element_attribute = ();
          }
        elsif ( $line =~ m/^\-(.*)$/i )
          {
            # This is parsed character text: $1.
            $pcdata = $1;

            # This text must be transformed if necessary.
	    #
	    # Notice that the \\ to \bsol translation and back is just
	    # an hack to resolve this problem inside SP records.
	    #
	    # Suppose we have:
	    #	bla bla bla \\no bla bla bla.
	    # If we translate the two \\ into a single \, we will have
	    #	bla bla bla \no bla bla bla.
	    # and then we will have a new line there. If the check
	    # the new line before, we will have
	    #	bla bla bla \
            #   o bla bla bla.
	    # with a residual \.
	    # But we wanted exactly.
	    #	bla bla bla \no bla bla bla.
	    # 
            $pcdata =~ s/\\\|//g;                 # \|            --> "" (SDATA residual delimiters)
            $pcdata =~ s/\\\\/\\bsol/g;           # \\            --> \bsol
            $pcdata =~ s/\\n/\n/g;                # \n            --> new line
            $pcdata =~ s/\\bsol/\\/g;             # \bsol         --> \
            
            # The text is released.
            &output ($pcdata);
          }
        elsif ( $line =~ m/^\C$/i )
          {
            # The file is OK.
            # Nothing to do.
            ;
          }
        else
          {
            # This is an unknown record type.
            &diag_output (sprintf (gettext ("%s: unknown post-SP record: %s"),
                           $program_executable, $line));
          }

      } # while

    # Close input file.
    close ($input_stream);

    # Close output stream and reset @output_stack.
    close ($current_output_stream);
    @output_stack = ();

} # sgml_post_sp_elab



#======================================================================
# Start of back-end program.
#----------------------------------------------------------------------

local ($sp_file_name)       = $ARGV[0];
local ($target)             = $ARGV[1];
local ($original_file_name) = $ARGV[2];
local ($root_file_name)     = $ARGV[3];
local ($paper)              = $ARGV[4];
local ($setchapternewpage)  = $ARGV[5];
local ($footnotestyle)      = $ARGV[6];
local ($headings) 	    = $ARGV[7];
local ($output_encoding)    = $ARGV[8];
local ($verbose)            = $ARGV[9];

# We have to elaborate the post-SP output 
# This elaboration will generate the file $root_file_name.texinfo
#
&sgml_post_sp_elab ($sp_file_name,
                    $target,
                    $original_file_name,
                    $root_file_name,
                    $paper,
                    $setchapternewpage,
                    $footnotestyle,
                    $headings,
		    $output_encoding);


#======================================================================

