-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset 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 distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with FileSystem;
with SystemErrors;

package body XMLReport
--# own State is File_Depth,
--#              Schema,
--#              Schema_State,
--#              Section_Depths,
--#              Tag_IDs,
--#              Tag_Strings;
is

   -- Set the version of the report file schema.  This should be the CVS version of the
   -- sparkreport.xsd file.
   Schema_Version : constant String := "1.8";

   type My_Tag is (
                   MT_Brief_Justifications,
                   MT_Commandline,
                   MT_Compiler_Data,
                   MT_Compiler_Item,
                   MT_Cyclic_Requirements,
                   MT_File,
                   MT_Filename,
                   MT_Full_Justification,
                   MT_Full_Justifications,
                   MT_Index,
                   MT_Indexes,
                   MT_Justifications_Section,
                   MT_Listing,
                   MT_Message,
                   MT_Messages,
                   MT_Metafile,
                   MT_Metafiles,
                   MT_Option,
                   MT_Prologue,
                   MT_Report,
                   MT_Results,
                   MT_Scope,
                   MT_Suppressed,
                   MT_Suppressed_Pragma,
                   MT_Symbol,
                   MT_Target_Config,
                   MT_Unit,
                   MT_Units_Notfound,
                   MT_Warnings_Config,
                   MT_Units_In_File);

   type Tag_String_Array is array (My_Tag) of E_Strings.T;
   type Tag_IDArray is array (My_Tag) of SPARK_XML.Tag_ID;
   type Section_Depth_Array is array (Sections) of SPARK_XML.Tag_Depth;

   -------------------
   -- Own Variables --
   -------------------

   -- Dictionary for the schema
   Tag_Strings : Tag_String_Array;
   Tag_IDs     : Tag_IDArray;

   -- The schema
   Schema       : SPARK_XML.Schema_Record;
   Schema_State : SPARK_XML.Schema_State_Record;

   -- Additional schema state info
   File_Depth     : SPARK_XML.Tag_Depth;
   Section_Depths : Section_Depth_Array;

   --------------------
   -- Error handling --
   --------------------

   procedure Handle_Error (Status : in SPARK_XML.Schema_Status)
   --# global in Schema;
   --#        in Schema_State;
   --# derives null from Schema,
   --#                   Schema_State,
   --#                   Status;
   is
   begin
      if SPARK_XML.Is_Error (Status) then
         SPARK_XML.Print_Schema_Error (Status);
         SPARK_XML.Print_Working_State (Schema, Schema_State);

         case Status is
            when SPARK_XML.SS_To_Many_Attributes =>
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.XML_Generation_Error,
                                         Msg     => "Exceeded Attribute Limit");
            when SPARK_XML.SS_Stack_Full =>
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.XML_Generation_Error,
                                         Msg     => "Exceeded XML Stack limit");
            when SPARK_XML.SS_Tag_Incomplete =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                  Msg     => "Attempted to gerenate incomplete tag");
            when SPARK_XML.SS_Invalid_Depth =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                  Msg     => "Invalid depth value for tag closure");
            when SPARK_XML.SS_Stack_Empty =>
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                                         Msg     => "Tag stack empty");
            when SPARK_XML.SS_Wrong_Content_Type =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                  Msg     => "Incorrect content type for attribute");
            when SPARK_XML.SS_Invalid_Attribute =>
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                                         Msg     => "Invalid attribute for tag");
            when SPARK_XML.SS_Invalid_Tag =>
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                                         Msg     => "Invalid tag");
            when SPARK_XML.SS_No_Such_Tag =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                  Msg     => "No such tag defined in schema");
            when SPARK_XML.SS_Tag_Not_Found =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                  Msg     => "Could not find instance of the tag to close");
            when SPARK_XML.SS_OK =>  -- We should never get to this case
               SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Illegal_XML_Generation_Attempt,
                                         Msg     => "Everything is fine");
         end case;
      end if;
   end Handle_Error;

   procedure Handle_Schema_Error (Success : in Boolean;
                                  Msg     : in String)
   --# derives null from Msg,
   --#                   Success;
   is
      --# hide Handle_Schema_Error;
   begin
      if not Success then
         SPARK_XML.Print_Working_State (Schema, Schema_State);
         SystemErrors.Fatal_Error (Sys_Err => SystemErrors.XML_Schema_Error,
                                   Msg     => Msg);
      end if;
   end Handle_Schema_Error;

   --------------------
   -- Initialisation --
   --------------------

   -- Build the dictionary, then create the schema representation for SPARK_XML

   procedure Init
   --# global out File_Depth;
   --#        out Schema;
   --#        out Schema_State;
   --#        out Section_Depths;
   --#        out Tag_IDs;
   --#        out Tag_Strings;
   --# derives File_Depth,
   --#         Schema,
   --#         Schema_State,
   --#         Section_Depths,
   --#         Tag_IDs,
   --#         Tag_Strings    from ;
   is

      -- Load the tag definitions in to the Schema
      procedure Load_Tags
      --# global in out Schema;
      --#           out Tag_IDs;
      --#           out Tag_Strings;
      --# derives Schema,
      --#         Tag_IDs     from Schema &
      --#         Tag_Strings from ;
      is
         Tmp_Tag : SPARK_XML.Tag_ID;
      begin
         Tag_Strings :=
           Tag_String_Array'
           (MT_Brief_Justifications   => E_Strings.Copy_String (Str => "brief_justifications"),
            MT_Commandline            => E_Strings.Copy_String (Str => "commandline"),
            MT_Compiler_Data          => E_Strings.Copy_String (Str => "compiler_data"),
            MT_Compiler_Item          => E_Strings.Copy_String (Str => "compiler_item"),
            MT_Cyclic_Requirements    => E_Strings.Copy_String (Str => "cyclic_requirements"),
            MT_File                   => E_Strings.Copy_String (Str => "file"),
            MT_Filename               => E_Strings.Copy_String (Str => "filename"),
            MT_Full_Justification     => E_Strings.Copy_String (Str => "full_justification"),
            MT_Full_Justifications    => E_Strings.Copy_String (Str => "full_justifications"),
            MT_Index                  => E_Strings.Copy_String (Str => "index"),
            MT_Indexes                => E_Strings.Copy_String (Str => "indexes"),
            MT_Justifications_Section => E_Strings.Copy_String (Str => "justifications_section"),
            MT_Listing                => E_Strings.Copy_String (Str => "listing"),
            MT_Message                => E_Strings.Copy_String (Str => "message"),
            MT_Messages               => E_Strings.Copy_String (Str => "messages"),
            MT_Metafile               => E_Strings.Copy_String (Str => "metafile"),
            MT_Metafiles              => E_Strings.Copy_String (Str => "metafiles"),
            MT_Option                 => E_Strings.Copy_String (Str => "option"),
            MT_Prologue               => E_Strings.Copy_String (Str => "prologue"),
            MT_Report                 => E_Strings.Copy_String (Str => "report"),
            MT_Results                => E_Strings.Copy_String (Str => "results"),
            MT_Scope                  => E_Strings.Copy_String (Str => "scope"),
            MT_Suppressed             => E_Strings.Copy_String (Str => "suppressed"),
            MT_Suppressed_Pragma      => E_Strings.Copy_String (Str => "pragma"),
            MT_Symbol                 => E_Strings.Copy_String (Str => "symbol"),
            MT_Target_Config          => E_Strings.Copy_String (Str => "target_config"),
            MT_Unit                   => E_Strings.Copy_String (Str => "unit"),
            MT_Units_Notfound         => E_Strings.Copy_String (Str => "units_notfound"),
            MT_Warnings_Config        => E_Strings.Copy_String (Str => "warnings_config"),
            MT_Units_In_File          => E_Strings.Copy_String (Str => "units"));

         Tag_IDs := Tag_IDArray'(others => SPARK_XML.Null_Tag);

         for I in My_Tag loop
            SPARK_XML.Add_Tag (Schema, Tag_Strings (I), Tmp_Tag);
            Tag_IDs (I) := Tmp_Tag;
            if SPARK_XML.Is_Null_Tag (Tmp_Tag) then
               -- Run out of room, so generate an error.
               Handle_Schema_Error (Success => False,
                                    Msg     => "Failure adding tag");
               exit;
            end if;
         end loop;
      end Load_Tags;

      -- Load the attribute definitions
      procedure Load_Attributes
      --# global in     Tag_IDs;
      --#        in out Schema;
      --# derives Schema from *,
      --#                     Tag_IDs;
      is
         -- Set Total_Attributes to the total number of attributes to be added
         -- to tags in the Schema.
         Total_Attributes : constant Integer := 25;

         type Attribute is record
            ID   : SPARK_XML.Tag_ID;
            Name : E_Strings.T;
            Typ  : SPARK_XML.Attribute_Type;
            Req  : Boolean;
         end record;

         type Attribute_Index is range 1 .. Total_Attributes;
         type Attribute_List is array (Attribute_Index) of Attribute;

         Tmp_Attrib  : SPARK_XML.Attribute_ID;
         Tmp_Success : Boolean;
         Attributes  : Attribute_List;
      begin
         -- This table encodes the legal attributes of each XML element, as specified
         -- in the SPARKReport Schema Description in sparkreport.xsd
         Attributes :=
           Attribute_List'
           (Attribute'(Tag_IDs (MT_Report), E_Strings.Copy_String (Str => "version"), SPARK_XML.At_String, True),

            Attribute'(Tag_IDs (MT_Symbol), E_Strings.Copy_String (Str => "id"), SPARK_XML.At_String, True),

            Attribute'(Tag_IDs (MT_Option), E_Strings.Copy_String (Str => "id"), SPARK_XML.At_String, False), -- Remove?

            Attribute'(Tag_IDs (MT_Unit), E_Strings.Copy_String (Str => "name"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Unit), E_Strings.Copy_String (Str => "type"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Unit), E_Strings.Copy_String (Str => "status"), SPARK_XML.At_String, False),

            Attribute'(Tag_IDs (MT_Message), E_Strings.Copy_String (Str => "class"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Message), E_Strings.Copy_String (Str => "code"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Message), E_Strings.Copy_String (Str => "line"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Message), E_Strings.Copy_String (Str => "offset"), SPARK_XML.At_Integer, True),

            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "class"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "code"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "line_from"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "line_to"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "match_no"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Full_Justification), E_Strings.Copy_String (Str => "match_line"), SPARK_XML.At_Integer, True),

            Attribute'(Tag_IDs (MT_Brief_Justifications), E_Strings.Copy_String (Str => "matched"), SPARK_XML.At_Integer, True),
            Attribute'(Tag_IDs (MT_Brief_Justifications), E_Strings.Copy_String (Str => "unmatched"), SPARK_XML.At_Integer, False),

            Attribute'(Tag_IDs (MT_Metafile), E_Strings.Copy_String (Str => "name"), SPARK_XML.At_String, True),

            Attribute'(Tag_IDs (MT_File), E_Strings.Copy_String (Str => "unit"), SPARK_XML.At_String, False),
            Attribute'(Tag_IDs (MT_File), E_Strings.Copy_String (Str => "type"), SPARK_XML.At_String, False),
            Attribute'(Tag_IDs (MT_File), E_Strings.Copy_String (Str => "filename"), SPARK_XML.At_String, True),

            Attribute'(Tag_IDs (MT_Compiler_Item), E_Strings.Copy_String (Str => "item"), SPARK_XML.At_String, True),

            Attribute'(Tag_IDs (MT_Scope), E_Strings.Copy_String (Str => "id"), SPARK_XML.At_String, True),
            Attribute'(Tag_IDs (MT_Scope), E_Strings.Copy_String (Str => "type"), SPARK_XML.At_String, True));

         for I in Attribute_Index loop
            --# accept Flow, 10, Tmp_Attrib, "Expected ineffective assignment to Tmp_Attrib";
            SPARK_XML.Add_Attribute_To_Tag
              (Schema, -- Expect ineffective statement
               Attributes (I).ID,
               Attributes (I).Name,
               Attributes (I).Typ,
               Attributes (I).Req,
               Tmp_Attrib,
               Tmp_Success);
            --# end accept;
            Handle_Schema_Error (Success => Tmp_Success,
                                 Msg     => "Failure adding attribute to tag");
            exit when not Tmp_Success;
         end loop;

         --# accept Flow, 33, Tmp_Attrib, "Expected to be neither referenced nor exported";
      end Load_Attributes;

      -- Load the hierarchy definitions
      procedure Build_Hierarchy
      --# global in     Tag_IDs;
      --#        in out Schema;
      --# derives Schema from *,
      --#                     Tag_IDs;
      is
         Max_Relations : constant Integer := 37;

         type Tag_Rel is record
            Parent   : SPARK_XML.Tag_ID;
            Child    : SPARK_XML.Tag_ID;
            Required : Boolean;
         end record;

         subtype Rel_Index is Integer range 1 .. Max_Relations;

         type Rel_Array is array (Rel_Index) of Tag_Rel;

         Relations   : Rel_Array;
         Tmp_Success : Boolean;
      begin
         -- This table encodes the legal nesting of XML elements, as specified
         -- in the SPARKReport Schema Description in sparkreport.xsd
         Relations :=
           Rel_Array'
           (Tag_Rel'(SPARK_XML.Null_Tag, Tag_IDs (MT_Report), False),

            Tag_Rel'(Tag_IDs (MT_Scope), Tag_IDs (MT_Scope), False),
            Tag_Rel'(Tag_IDs (MT_Scope), Tag_IDs (MT_Message), False),

            Tag_Rel'(Tag_IDs (MT_Message), Tag_IDs (MT_Symbol), False),

            Tag_Rel'(Tag_IDs (MT_Report), Tag_IDs (MT_Prologue), False),
            Tag_Rel'(Tag_IDs (MT_Report), Tag_IDs (MT_Results), False),

            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Commandline), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Indexes), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Metafiles), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Warnings_Config), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Compiler_Data), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Target_Config), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Units_Notfound), False),
            Tag_Rel'(Tag_IDs (MT_Prologue), Tag_IDs (MT_Cyclic_Requirements), False),

            Tag_Rel'(Tag_IDs (MT_Commandline), Tag_IDs (MT_Filename), False),
            Tag_Rel'(Tag_IDs (MT_Commandline), Tag_IDs (MT_Option), False),

            Tag_Rel'(Tag_IDs (MT_Compiler_Data), Tag_IDs (MT_Compiler_Item), False),

            Tag_Rel'(Tag_IDs (MT_Cyclic_Requirements), Tag_IDs (MT_Unit), False),

            Tag_Rel'(Tag_IDs (MT_Indexes), Tag_IDs (MT_Index), False),

            Tag_Rel'(Tag_IDs (MT_Target_Config), Tag_IDs (MT_Filename), False),
            Tag_Rel'(Tag_IDs (MT_Target_Config), Tag_IDs (MT_Messages), False),

            Tag_Rel'(Tag_IDs (MT_Messages), Tag_IDs (MT_Message), False),

            Tag_Rel'(Tag_IDs (MT_Metafiles), Tag_IDs (MT_Metafile), False),

            Tag_Rel'(Tag_IDs (MT_Metafile), Tag_IDs (MT_Metafile), False),
            Tag_Rel'(Tag_IDs (MT_Metafile), Tag_IDs (MT_Filename), False),

            Tag_Rel'(Tag_IDs (MT_Units_Notfound), Tag_IDs (MT_Unit), False),

            Tag_Rel'(Tag_IDs (MT_Warnings_Config), Tag_IDs (MT_Suppressed), False),
            Tag_Rel'(Tag_IDs (MT_Warnings_Config), Tag_IDs (MT_Suppressed_Pragma), False),

            Tag_Rel'(Tag_IDs (MT_File), Tag_IDs (MT_Units_In_File), False),
            Tag_Rel'(Tag_IDs (MT_File), Tag_IDs (MT_Scope), False),
            Tag_Rel'(Tag_IDs (MT_File), Tag_IDs (MT_Message), False),
            Tag_Rel'(Tag_IDs (MT_File), Tag_IDs (MT_Justifications_Section), False),

            Tag_Rel'(Tag_IDs (MT_Justifications_Section), Tag_IDs (MT_Full_Justifications), False),
            Tag_Rel'(Tag_IDs (MT_Justifications_Section), Tag_IDs (MT_Brief_Justifications), False),

            Tag_Rel'(Tag_IDs (MT_Full_Justifications), Tag_IDs (MT_Full_Justification), False),

            Tag_Rel'(Tag_IDs (MT_Units_In_File), Tag_IDs (MT_Unit), False),

            Tag_Rel'(Tag_IDs (MT_Results), Tag_IDs (MT_File), False));

         for I in Rel_Index loop
            SPARK_XML.Add_Child_Tag (Schema, Relations (I).Parent, Relations (I).Child, Relations (I).Required, Tmp_Success);
            Handle_Schema_Error (Success => Tmp_Success,
                                 Msg     => "Failure loading tag hierarchy");
            exit when not Tmp_Success;
         end loop;
      end Build_Hierarchy;

   begin
      Section_Depths := Section_Depth_Array'(others => SPARK_XML.Tag_Depth'First);
      File_Depth     := SPARK_XML.Tag_Depth'First;

      SPARK_XML.Init_Schema (Schema);
      SPARK_XML.Init_Schema_State (Schema_State);

      Load_Tags;
      Load_Attributes;
      Build_Hierarchy;
   end Init;

   ------------------------------------------------------------------------
   -- Tag producing functions                                            --
   ------------------------------------------------------------------------

   ------------------------------------------------------------------------
   -- Producers for simple container tags.                               --
   -- These have no attributes of their own and only contain other tags. --
   -- The only exception is the Listing tag, which contains large        --
   -- amounts of text, and is also included.                             --
   ------------------------------------------------------------------------

   procedure Start_Section (Section : in Sections;
                            Report  : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out Section_Depths;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State,
   --#         Section_Depths    from *,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Section,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Section,
   --#                                Tag_IDs;
   is
      Tag    : SPARK_XML.Tag_ID;
      Status : SPARK_XML.Schema_Status;
      Depth  : SPARK_XML.Tag_Depth;
      XML    : E_Strings.T;
   begin
      case Section is
         when S_Report =>
            Tag := Tag_IDs (MT_Report);
         when S_Prologue =>
            Tag := Tag_IDs (MT_Prologue);
         when S_Commandline =>
            Tag := Tag_IDs (MT_Commandline);
         when S_Compiler_Data =>
            Tag := Tag_IDs (MT_Compiler_Data);
         when S_Cyclic_Requirements =>
            Tag := Tag_IDs (MT_Cyclic_Requirements);
         when S_Indexes =>
            Tag := Tag_IDs (MT_Indexes);
         when S_Target_Config =>
            Tag := Tag_IDs (MT_Target_Config);
         when S_Messages =>
            Tag := Tag_IDs (MT_Messages);
         when S_Meta_Files =>
            Tag := Tag_IDs (MT_Metafiles);
         when S_Units_Not_Found =>
            Tag := Tag_IDs (MT_Units_Notfound);
         when S_Warnings_Config =>
            Tag := Tag_IDs (MT_Warnings_Config);
         when S_Results =>
            Tag := Tag_IDs (MT_Results);
         when S_Listing =>
            Tag := Tag_IDs (MT_Listing);
         when S_Units_In_File =>
            Tag := Tag_IDs (MT_Units_In_File);
         when S_Justifications =>
            Tag := Tag_IDs (MT_Justifications_Section);
         when S_Full_Justifications =>
            Tag := Tag_IDs (MT_Full_Justifications);
      end case;

      SPARK_XML.Init_Opening_Tag_By_ID (Schema       => Schema,
                                        Schema_State => Schema_State,
                                        TID          => Tag,
                                        Status       => Status);

      Handle_Error (Status => Status);

      if Section = S_Report then
         SPARK_XML.Add_Attribute_Str
           (Schema       => Schema,
            Schema_State => Schema_State,
            Name         => E_Strings.Copy_String (Str => "version"),
            Value        => E_Strings.Copy_String (Str => Schema_Version),
            Status       => Status);
         Handle_Error (Status => Status);
      end if;

      SPARK_XML.Output_Opening_Tag (Schema       => Schema,
                                    Schema_State => Schema_State,
                                    XML          => XML,
                                    Depth        => Depth,
                                    Status       => Status);
      Section_Depths (Section) := Depth;

      Handle_Error (Status => Status);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end Start_Section;

   procedure End_Section (Section : in Sections;
                          Report  : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Section_Depths;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Section,
   --#                                Section_Depths &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Section,
   --#                                Section_Depths;
   is
      Status : SPARK_XML.Schema_Status;
      XML    : E_Strings.T;
   begin
      SPARK_XML.Close_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         Depth        => Section_Depths (Section),
         XML          => XML,
         Status       => Status);
      Handle_Error (Status => Status);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end End_Section;

   -- Simple tags, ones whose opening and closing tags are generated
   -- at the same time, with simple text contents
   -- E.g. <filename>file.txt</filename>
   procedure Simple_Tag (Tag      : in     SPARK_XML.Tag_ID;
                         Contents : in out E_Strings.T)
   --# global in     Schema;
   --#        in out Schema_State;
   --# derives Contents,
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag;
   is
      Acc_XML, Tmp_XML : E_Strings.T;  -- XML accumulator and temp variable.
      Depth            : SPARK_XML.Tag_Depth;
      Status           : SPARK_XML.Schema_Status;
   begin
      SPARK_XML.Init_Opening_Tag_By_ID (Schema       => Schema,
                                        Schema_State => Schema_State,
                                        TID          => Tag,
                                        Status       => Status);
      Handle_Error (Status => Status);
      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => Acc_XML,
         Depth        => Depth,
         Status       => Status);
      Handle_Error (Status => Status);
      E_Strings.Append_Examiner_String (E_Str1 => Acc_XML,
                                        E_Str2 => SPARK_XML.Filter_String (Str => Contents));
      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => Depth,
                           XML          => Tmp_XML,
                           Status       => Status);
      E_Strings.Append_Examiner_String (E_Str1 => Acc_XML,
                                        E_Str2 => Tmp_XML);
      Handle_Error (Status => Status);
      Contents := Acc_XML;
   end Simple_Tag;

   procedure Filename (Plain_Output : in     Boolean;
                       File         : in out E_Strings.T)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --# derives File         from *,
   --#                           Plain_Output,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag_IDs &
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Tag_IDs;
   is
   begin
      if Plain_Output then
         File := FileSystem.Just_File (Fn  => File,
                                       Ext => True);
      end if;
      Simple_Tag (Tag      => Tag_IDs (MT_Filename),
                  Contents => File);
   end Filename;

   procedure Index (Plain_Output : in     Boolean;
                    Idx          : in out E_Strings.T)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --# derives Idx          from *,
   --#                           Plain_Output,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag_IDs &
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Tag_IDs;
   is
   begin
      if Plain_Output then
         Idx := FileSystem.Just_File (Idx, True);
      end if;
      Simple_Tag (Tag      => Tag_IDs (MT_Index),
                  Contents => Idx);
   end Index;

   procedure Option (Opt : in out E_Strings.T)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --# derives Opt,
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag_IDs;
   is
   begin
      Simple_Tag (Tag      => Tag_IDs (MT_Option),
                  Contents => Opt);
   end Option;

   procedure Suppressed (Item : in out E_Strings.T)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --# derives Item,
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag_IDs;
   is
   begin
      Simple_Tag (Tag      => Tag_IDs (MT_Suppressed),
                  Contents => Item);
   end Suppressed;

   procedure Suppressed_Pragma (Item : in out E_Strings.T)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --# derives Item,
   --#         Schema_State from *,
   --#                           Schema,
   --#                           Schema_State,
   --#                           Tag_IDs;
   is
   begin
      Simple_Tag (Tag      => Tag_IDs (MT_Suppressed_Pragma),
                  Contents => Item);
   end Suppressed_Pragma;

   ---------------------------------------------
   -- More complex tags that have attributes. --
   ---------------------------------------------

   procedure Open_Compiler_Item (Item   : in     E_Strings.T;
                                 Depth  :    out SPARK_XML.Tag_Depth;
                                 Report : in     SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Depth,
   --#         Schema_State      from Item,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Item,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;

   is
      Acc_XML : E_Strings.T;  -- XML accumulator and temp variable.
      Stat    : SPARK_XML.Schema_Status;
   begin
      SPARK_XML.Init_Opening_Tag_By_ID
        (Schema       => Schema,
         Schema_State => Schema_State,
         TID          => Tag_IDs (MT_Compiler_Item),
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "item"),
         Value        => Item,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => Acc_XML,
         Depth        => Depth,
         Status       => Stat);
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);  -- Output the opening tag
   end Open_Compiler_Item;

   procedure Close_Compiler_Item (Depth  : in SPARK_XML.Tag_Depth;
                                  Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Depth &
   --#         SPARK_IO.File_Sys from *,
   --#                                Depth,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State;
   is
      Acc_XML : E_Strings.T;  -- XML accumulator and temp variable.
      Stat    : SPARK_XML.Schema_Status;
   begin

      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => Depth,
                           XML          => Acc_XML,
                           Status       => Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);

   end Close_Compiler_Item;

   procedure Compiler_Item (Item   : in E_Strings.T;
                            Val    : in E_Strings.T;
                            Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Item,
   --#                                Schema,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Item,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs,
   --#                                Val;
   is
      Depth : SPARK_XML.Tag_Depth;
   begin
      Open_Compiler_Item (Item   => Item,
                          Depth  => Depth,
                          Report => Report);

      E_Strings.Put_String (File  => Report,
                            E_Str => SPARK_XML.Filter_String (Str => Val));  -- Output the value

      Close_Compiler_Item (Depth  => Depth,
                           Report => Report);
   end Compiler_Item;

   procedure Unit (Name   : in E_Strings.T;
                   Typ    : in E_Strings.T;
                   Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Name,
   --#                                Schema,
   --#                                Tag_IDs,
   --#                                Typ &
   --#         SPARK_IO.File_Sys from *,
   --#                                Name,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs,
   --#                                Typ;
   is
      Acc_XML, Tmp_XML : E_Strings.T;  -- XML accumulator and temp variable.
      Depth            : SPARK_XML.Tag_Depth;
      Stat             : SPARK_XML.Schema_Status;
   begin

      SPARK_XML.Init_Opening_Tag_By_ID (Schema       => Schema,
                                        Schema_State => Schema_State,
                                        TID          => Tag_IDs (MT_Unit),
                                        Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "name"),
         Value        => Name,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "type"),
         Value        => Typ,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => Acc_XML,
         Depth        => Depth,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => Depth,
                           XML          => Tmp_XML,
                           Status       => Stat);

      E_Strings.Append_Examiner_String (E_Str1 => Acc_XML,
                                        E_Str2 => Tmp_XML);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);

   end Unit;

   procedure Ada_Unit
     (Name        : in E_Strings.T;
      Typ         : in E_Strings.T;
      Unit_Status : in E_Strings.T;
      Report      : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Name,
   --#                                Schema,
   --#                                Tag_IDs,
   --#                                Typ,
   --#                                Unit_Status &
   --#         SPARK_IO.File_Sys from *,
   --#                                Name,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs,
   --#                                Typ,
   --#                                Unit_Status;
   is
      Acc_XML : E_Strings.T;  -- XML accumulator.
      Depth   : SPARK_XML.Tag_Depth;    -- Dummy variable.
      Stat    : SPARK_XML.Schema_Status;
   begin

      SPARK_XML.Init_Opening_Tag_By_ID (Schema       => Schema,
                                        Schema_State => Schema_State,
                                        TID          => Tag_IDs (MT_Unit),
                                        Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "name"),
         Value        => Name,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "type"),
         Value        => Typ,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "status"),
         Value        => Unit_Status,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => Acc_XML,
         Depth        => Depth,
         Status       => Stat);
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);

      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => Depth,
                           XML          => Acc_XML,
                           Status       => Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);

   end Ada_Unit;  -- Depth is neither referenced or exported.

   ---------------------------
   -- Message construction. --
   ---------------------------

   procedure Start_Message
     (Class  : in E_Strings.T;
      Code   : in Integer;
      Line   : in Integer;
      Offset : in Integer;
      Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Class,
   --#                                Code,
   --#                                Line,
   --#                                Offset,
   --#                                Schema,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Class,
   --#                                Code,
   --#                                Line,
   --#                                Offset,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Depth : SPARK_XML.Tag_Depth;
      Stat  : SPARK_XML.Schema_Status;
      XML   : E_Strings.T;
   begin
      SPARK_XML.Init_Opening_Tag_No_Check (Schema_State => Schema_State,
                                           TID          => Tag_IDs (MT_Message),
                                           Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "class"),
         Value        => Class,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "code"), Code, Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "line"), Line, Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "offset"), Offset, Stat);
      Handle_Error (Status => Stat);

      --# accept Flow, 10, Depth, "Expected ineffective assignment to Depth";
      SPARK_XML.Output_Opening_Tag (Schema       => Schema,
                                    Schema_State => Schema_State,
                                    XML          => XML,
                                    Depth        => Depth,
                                    Status       => Stat);
      --# end accept;
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);

      --# accept Flow, 33, Depth, "Expected Depth to be neither referenced nor exported";
   end Start_Message;

   procedure Symbol (Sym     : in E_Strings.T;
                     Sym_Num : in Integer;
                     Report  : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Schema,
   --#                                Sym_Num,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Sym,
   --#                                Sym_Num,
   --#                                Tag_IDs;
   is
      Acc_XML, Tmp_XML : E_Strings.T;  -- XML accumulator and temp variable.
      Depth            : SPARK_XML.Tag_Depth;
      Stat             : SPARK_XML.Schema_Status;
   begin
      SPARK_XML.Init_Opening_Tag_By_ID
        (Schema       => Schema,
         Schema_State => Schema_State,
         TID          => Tag_IDs (MT_Symbol),
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "id"), Sym_Num, Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => Acc_XML,
         Depth        => Depth,
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the symbol contents.
      E_Strings.Append_Examiner_String (E_Str1 => Acc_XML,
                                        E_Str2 => SPARK_XML.Filter_String (Str => Sym));

      -- Close the tag.
      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => Depth,
                           XML          => Tmp_XML,
                           Status       => Stat);
      Handle_Error (Status => Stat);
      E_Strings.Append_Examiner_String (E_Str1 => Acc_XML,
                                        E_Str2 => Tmp_XML);

      E_Strings.Put_String (File  => Report,
                            E_Str => Acc_XML);
   end Symbol;

   -- End_Message will close the open message (of which there will be one
   -- in the hierarchy since only a <symbol> can be placed in a <message>
   procedure End_Message (Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
   begin
      SPARK_XML.Close_Tag_By_ID (Schema, Schema_State, Tag_IDs (MT_Message), XML, Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end End_Message;

   --------------------------
   -- Metafile contruction --
   --------------------------

   procedure Start_Meta_File (Name   : in E_Strings.T;
                              Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Name,
   --#                                Schema,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Name,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
      Id   : SPARK_XML.Tag_Depth;
   begin
      -- Generate the XML

      SPARK_XML.Init_Opening_Tag_By_ID
        (Schema       => Schema,
         Schema_State => Schema_State,
         TID          => Tag_IDs (MT_Metafile),
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "name"),
         Value        => Name,
         Status       => Stat);
      Handle_Error (Status => Stat);

      --# accept Flow, 10, Id, "Expected ineffective assignment to Id";
      SPARK_XML.Output_Opening_Tag (Schema       => Schema,
                                    Schema_State => Schema_State,
                                    XML          => XML,
                                    Depth        => Id,
                                    Status       => Stat);
      --# end accept;
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);

      --# accept Flow, 33, Id, "Expected Id to be neither referenced nor exported";
   end Start_Meta_File;

   procedure End_Meta_File (Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
   begin
      SPARK_XML.Close_Top_Tag_By_ID (Schema, Schema_State, Tag_IDs (MT_Metafile), XML, Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end End_Meta_File;

   ------------------------------
   -- Results Section contents --
   ------------------------------
   procedure Start_File (Plain_Output : in Boolean;
                         F_Name       : in E_Strings.T;
                         Report       : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --#           out File_Depth;
   --# derives File_Depth,
   --#         Schema_State      from F_Name,
   --#                                Plain_Output,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                F_Name,
   --#                                Plain_Output,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
   begin
      SPARK_XML.Init_Opening_Tag_No_Check (Schema_State => Schema_State,
                                           TID          => Tag_IDs (MT_File),
                                           Status       => Stat);
      Handle_Error (Status => Stat);
      -- Add the attributes
      if Plain_Output then
         SPARK_XML.Add_Attribute_Str
           (Schema       => Schema,
            Schema_State => Schema_State,
            Name         => E_Strings.Copy_String (Str => "filename"),
            Value        => FileSystem.Just_File (Fn  => F_Name,
                                                  Ext => True),
            Status       => Stat);
      else
         SPARK_XML.Add_Attribute_Str
           (Schema       => Schema,
            Schema_State => Schema_State,
            Name         => E_Strings.Copy_String (Str => "filename"),
            Value        => F_Name,
            Status       => Stat);
      end if;
      Handle_Error (Status => Stat);
      SPARK_XML.Output_Opening_Tag
        (Schema       => Schema,
         Schema_State => Schema_State,
         XML          => XML,
         Depth        => File_Depth,
         Status       => Stat);
      Handle_Error (Status => Stat);
      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end Start_File;

   procedure End_File (Report : in SPARK_IO.File_Type)
   --# global in     File_Depth;
   --#        in     Schema;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                File_Depth &
   --#         SPARK_IO.File_Sys from *,
   --#                                File_Depth,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
   begin
      -- Close the tag.
      SPARK_XML.Close_Tag (Schema       => Schema,
                           Schema_State => Schema_State,
                           Depth        => File_Depth,
                           XML          => XML,
                           Status       => Stat);
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end End_File;

   --------------------------
   -- Justification output --
   --------------------------

   procedure Brief_Justifications (Matched   : in Natural;
                                   Unmatched : in Natural;
                                   Report    : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Matched,
   --#                                Schema,
   --#                                Tag_IDs,
   --#                                Unmatched &
   --#         SPARK_IO.File_Sys from *,
   --#                                Matched,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs,
   --#                                Unmatched;
   is
      Depth : SPARK_XML.Tag_Depth;
      Stat  : SPARK_XML.Schema_Status;
      XML   : E_Strings.T;
   begin
      SPARK_XML.Init_Opening_Tag_By_ID
        (Schema       => Schema,
         Schema_State => Schema_State,
         TID          => Tag_IDs (MT_Brief_Justifications),
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "matched"), Matched, Stat);
      Handle_Error (Status => Stat);

      if Unmatched > 0 then
         SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "unmatched"), Unmatched, Stat);

         Handle_Error (Status => Stat);
      end if;

      --# accept Flow, 10, Depth, "Expected ineffective assignment to Depth";
      SPARK_XML.Output_Opening_Tag (Schema       => Schema,
                                    Schema_State => Schema_State,
                                    XML          => XML,
                                    Depth        => Depth,
                                    Status       => Stat);
      --# end accept;
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);

      SPARK_XML.Close_Tag_By_ID (Schema, Schema_State, Tag_IDs (MT_Brief_Justifications), XML, Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);

      --# accept Flow, 33, Depth, "Expected Depth to be neither referenced nor exported";
   end Brief_Justifications;

   procedure Start_Full_Justification
     (Class      : in E_Strings.T;
      Code       : in Integer;
      Line_From  : in Integer;
      Line_To    : in E_Strings.T;
      Match_No   : in Integer;
      Match_Line : in Integer;
      Report     : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Class,
   --#                                Code,
   --#                                Line_From,
   --#                                Line_To,
   --#                                Match_Line,
   --#                                Match_No,
   --#                                Schema,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Class,
   --#                                Code,
   --#                                Line_From,
   --#                                Line_To,
   --#                                Match_Line,
   --#                                Match_No,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Depth : SPARK_XML.Tag_Depth;
      Stat  : SPARK_XML.Schema_Status;
      XML   : E_Strings.T;
   begin
      SPARK_XML.Init_Opening_Tag_By_ID
        (Schema       => Schema,
         Schema_State => Schema_State,
         TID          => Tag_IDs (MT_Full_Justification),
         Status       => Stat);
      Handle_Error (Status => Stat);

      -- Add the attributes

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "class"),
         Value        => Class,
         Status       => Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "code"), Code, Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "line_from"), Line_From, Stat);
      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Str
        (Schema       => Schema,
         Schema_State => Schema_State,
         Name         => E_Strings.Copy_String (Str => "line_to"),
         Value        => Line_To,
         Status       => Stat);

      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "match_no"), Match_No, Stat);

      Handle_Error (Status => Stat);

      SPARK_XML.Add_Attribute_Int (Schema, Schema_State, E_Strings.Copy_String (Str => "match_line"), Match_Line, Stat);

      Handle_Error (Status => Stat);

      --# accept Flow, 10, Depth, "Expected ineffective assignment to Depth";
      SPARK_XML.Output_Opening_Tag (Schema       => Schema,
                                    Schema_State => Schema_State,
                                    XML          => XML,
                                    Depth        => Depth,
                                    Status       => Stat);
      --# end accept;
      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);

      --# accept Flow, 33, Depth, "Expected Depth to be neither referenced nor exported";
   end Start_Full_Justification;

   procedure End_Full_Justification (Report : in SPARK_IO.File_Type)
   --# global in     Schema;
   --#        in     Tag_IDs;
   --#        in out Schema_State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Schema_State      from *,
   --#                                Tag_IDs &
   --#         SPARK_IO.File_Sys from *,
   --#                                Report,
   --#                                Schema,
   --#                                Schema_State,
   --#                                Tag_IDs;
   is
      Stat : SPARK_XML.Schema_Status;
      XML  : E_Strings.T;
   begin
      SPARK_XML.Close_Tag_By_ID (Schema, Schema_State, Tag_IDs (MT_Full_Justification), XML, Stat);

      Handle_Error (Status => Stat);

      E_Strings.Put_String (File  => Report,
                            E_Str => XML);
   end End_Full_Justification;

end XMLReport;
