-------------------------------------------------------------------------------
-- (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 Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with CommandLineData;
with E_Strings;
with Heap;
with LexTokenManager;
with LexTokenManager.Relation_Algebra;
with LexTokenManager.Relation_Algebra.String;
with LexTokenManager.Seq_Algebra;
with SeqAlgebra;
with SparkFormatCommandLineData;
with SparkLex;
with SP_Symbols;

use type LexTokenManager.Str_Comp_Result;
use type SeqAlgebra.MemberOfSeq;
use type SparkFormatCommandLineData.Expand_Or_Compress;
use type SP_Symbols.SP_Terminal;

package body SPARKProgram is

   --# inherit Ada.Characters.Latin_1,
   --#         E_Strings;
   package White_Space is

      function Is_White_Space (Char : Character) return Boolean;

      procedure Skip (Input_Line : in     E_Strings.T;
                      Index      : in out E_Strings.Lengths);
      --# derives Index from *,
      --#                    Input_Line;

   end White_Space;

   --# inherit CommandLineData,
   --#         Dictionary,
   --#         ErrorHandler,
   --#         E_Strings,
   --#         LexTokenManager,
   --#         SparkLex,
   --#         SPARK_IO,
   --#         SP_Symbols,
   --#         White_Space;
   package File_IO is

      procedure Create (Temporary_File : in out SPARK_IO.File_Type);
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys,
      --#         Temporary_File    from SPARK_IO.File_Sys,
      --#                                Temporary_File;

      procedure Reset (Temporary_File : in out SPARK_IO.File_Type);
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys,
      --#         Temporary_File    from *,
      --#                                Temporary_File;

      procedure Delete (Temporary_File : in out SPARK_IO.File_Type);
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys,
      --#         Temporary_File    from *,
      --#                                Temporary_File;

      procedure Lex
        (Temporary_File : in     SPARK_IO.File_Type;
         Token          :    out SP_Symbols.SP_Terminal;
         Lex_Val        :    out LexTokenManager.Lex_Value);
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out LexTokenManager.State;
      --#        in out SparkLex.Curr_Line;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         LexTokenManager.State,
      --#         Lex_Val,
      --#         SparkLex.Curr_Line,
      --#         SPARK_IO.File_Sys,
      --#         Token                      from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         SparkLex.Curr_Line,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Temporary_File;

   end File_IO;

   --# inherit Heap,
   --#         LexTokenManager,
   --#         LexTokenManager.Seq_Algebra,
   --#         SeqAlgebra,
   --#         White_Space;
   package Iteration is

      type Iterator is private;

      procedure Initialise
        (The_Heap     : in     Heap.HeapRecord;
         The_Seq      : in     LexTokenManager.Seq_Algebra.Seq;
         The_Iterator :    out Iterator);
      --# global in LexTokenManager.State;
      --# derives The_Iterator from LexTokenManager.State,
      --#                           The_Heap,
      --#                           The_Seq;

      procedure Next (The_Heap     : in     Heap.HeapRecord;
                      The_Iterator : in out Iterator);
      --# global in LexTokenManager.State;
      --# derives The_Iterator from *,
      --#                           LexTokenManager.State,
      --#                           The_Heap;

      function Complete (The_Iterator : Iterator) return Boolean;

      function Current_String (The_Iterator : Iterator) return LexTokenManager.Lex_String;

      function Current_Member (The_Iterator : Iterator) return LexTokenManager.Seq_Algebra.Member_Of_Seq;

   private

      type Iterator is record
         First_Member   : LexTokenManager.Seq_Algebra.Member_Of_Seq;
         Current_Member : LexTokenManager.Seq_Algebra.Member_Of_Seq;
         Placeholder    : LexTokenManager.Lex_String;
         Complete       : Boolean;
      end record;

   end Iteration;

   --# inherit Ada.Characters.Handling,
   --#         CommandLineData,
   --#         E_Strings,
   --#         SparkFormatCommandLineData,
   --#         SPARK_IO,
   --#         White_Space;
   package Annotations is

      type Anno_Type is private;

      procedure Initialize
        (This        :    out Anno_Type;
         Anno_Intro  : in     String;
         Anno_Succ   : in     String;
         Anno_Indent : in     Natural);
      --# global in CommandLineData.Content;
      --# derives This from Anno_Indent,
      --#                   Anno_Intro,
      --#                   Anno_Succ,
      --#                   CommandLineData.Content;

      function Intro (This : Anno_Type) return E_Strings.T;

      function Indent (This : Anno_Type) return Natural;

      procedure Is_Anno_Start
        (This       : in     Anno_Type;
         Input_Line : in     E_Strings.T;
         Index      : in out E_Strings.Lengths;
         OK         :    out Boolean);
      --# derives Index,
      --#         OK    from Index,
      --#                    Input_Line,
      --#                    This;

      function Is_Start_Of (This       : Anno_Type;
                            Input_Line : E_Strings.T) return Boolean;

      function Is_End_Of (This       : Anno_Type;
                          Input_Line : E_Strings.T) return Boolean;

      function Proper_Start_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions;

      procedure Write (This      : in Anno_Type;
                       Output    : in SPARK_IO.File_Type;
                       Start_Col : in E_Strings.Positions);
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys from *,
      --#                                Output,
      --#                                Start_Col,
      --#                                This;

      procedure Write_Intro (This      : in Anno_Type;
                             Output    : in SPARK_IO.File_Type;
                             Start_Col : in E_Strings.Positions);
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys from *,
      --#                                Output,
      --#                                Start_Col,
      --#                                This;

      function Name1_Start_Col (This      : in Anno_Type;
                                Start_Col : in E_Strings.Positions) return E_Strings.Positions;

   private
      subtype Anno_Start_Bounds is Positive range 1 .. 3;
      subtype Anno_Start_Type is String (Anno_Start_Bounds);

      type Anno_Type is record
         Anno_Start  : Anno_Start_Type;
         Anno_Intro  : E_Strings.T;
         Anno_Succ   : E_Strings.T;
         Anno_Indent : Natural;
      end record;
   end Annotations;

   --# inherit Ada.Characters.Handling,
   --#         Ada.Characters.Latin_1,
   --#         Annotations,
   --#         CommandLineData,
   --#         Dictionary,
   --#         ErrorHandler,
   --#         E_Strings,
   --#         File_IO,
   --#         Heap,
   --#         Iteration,
   --#         LexTokenManager,
   --#         LexTokenManager.Relation_Algebra,
   --#         LexTokenManager.Relation_Algebra.String,
   --#         LexTokenManager.Seq_Algebra,
   --#         RelationAlgebra,
   --#         SeqAlgebra,
   --#         SparkFormatCommandLineData,
   --#         SparkLex,
   --#         SPARKProgram,
   --#         SPARK_IO,
   --#         SP_Symbols,
   --#         Statistics,
   --#         White_Space;
   package Reformatter is

      Allow_Dotted_Names_Const    : constant Boolean := True;
      Disallow_Dotted_Names_Const : constant Boolean := False;

      type State is private;

      procedure Initialise
        (Anno         : in     Annotations.Anno_Type;
         Dotted_Names : in     Boolean;
         The_Heap     : in out Heap.HeapRecord;
         This         :    out State);
      --# global in out Statistics.TableUsage;
      --# derives Statistics.TableUsage,
      --#         The_Heap              from *,
      --#                                    The_Heap &
      --#         This                  from Anno,
      --#                                    Dotted_Names,
      --#                                    The_Heap;

      procedure Parse (This           : in out State;
                       The_Heap       : in out Heap.HeapRecord;
                       Temporary_File : in out SPARK_IO.File_Type);
      --# global in     CommandLineData.Content;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --# derives LexTokenManager.State,
      --#         The_Heap              from *,
      --#                                    CommandLineData.Content,
      --#                                    LexTokenManager.State,
      --#                                    SPARK_IO.File_Sys,
      --#                                    Temporary_File,
      --#                                    This &
      --#         SPARK_IO.File_Sys     from *,
      --#                                    CommandLineData.Content,
      --#                                    Temporary_File,
      --#                                    This &
      --#         Statistics.TableUsage,
      --#         This                  from *,
      --#                                    CommandLineData.Content,
      --#                                    LexTokenManager.State,
      --#                                    SPARK_IO.File_Sys,
      --#                                    Temporary_File,
      --#                                    The_Heap,
      --#                                    This &
      --#         Temporary_File        from *;

      procedure Reformat
        (This           : in     State;
         The_Heap       : in out Heap.HeapRecord;
         Temporary_File : in out SPARK_IO.File_Type;
         Output         : in     SPARK_IO.File_Type;
         Success        :    out Boolean);
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in     SparkFormatCommandLineData.Content;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --# derives SPARK_IO.File_Sys     from *,
      --#                                    CommandLineData.Content,
      --#                                    LexTokenManager.State,
      --#                                    Output,
      --#                                    SparkFormatCommandLineData.Content,
      --#                                    Temporary_File,
      --#                                    The_Heap,
      --#                                    This &
      --#         Statistics.TableUsage,
      --#         The_Heap              from *,
      --#                                    LexTokenManager.State,
      --#                                    SparkFormatCommandLineData.Content,
      --#                                    The_Heap,
      --#                                    This &
      --#         Success               from This &
      --#         Temporary_File        from *,
      --#                                    This;

      procedure Finalise (This     : in out State;
                          The_Heap : in out Heap.HeapRecord);
      --# derives The_Heap,
      --#         This     from *,
      --#                       This;

   private
      type Relation_Type is record
         Modifier_Rel : LexTokenManager.Relation_Algebra.Relation;
         Type_Rel     : LexTokenManager.Relation_Algebra.String.Relation;
         Property_Rel : LexTokenManager.Relation_Algebra.String.Relation;
      end record;

      type Variable_Modifier is (
                                 Unmoded,
                                 In_Mode,
                                 Out_Mode,
                                 In_Out_Mode,
                                 Protected_Unmoded,
                                 Protected_In,
                                 Protected_Out,
                                 Task_Modifier);
      type Modifier_Use is array (Variable_Modifier) of Boolean;

      type Statistics_Type is record
         Start_Col             : E_Strings.Positions;
         Max_Modifier_Length   : E_Strings.Lengths;
         Max_Primary_Id_Length : E_Strings.Lengths;
         Max_Type_Mark_Length  : E_Strings.Lengths;
         Modifiers_Present     : Modifier_Use;
         Type_Mark_Present     : Boolean;
         Property_List_Present : Boolean;
      end record;

      type State is record
         Anno               : Annotations.Anno_Type;
         Relations          : Relation_Type;
         Parse_Stats        : Statistics_Type;
         Allow_Dotted_Names : Boolean;
         Success            : Boolean;
      end record;

   end Reformatter;

   package body White_Space is

      function Is_White_Space (Char : Character) return Boolean is
      begin
         --Note that: Ada.Characters.Latin_1.HT is a tab.
         return Char = Ada.Characters.Latin_1.Space or Char = Ada.Characters.Latin_1.HT;
      end Is_White_Space;

      procedure Skip (Input_Line : in     E_Strings.T;
                      Index      : in out E_Strings.Lengths) is
      begin
         loop
            exit when Index >= E_Strings.Get_Length (E_Str => Input_Line)
              or else not Is_White_Space (Char => E_Strings.Get_Element (E_Str => Input_Line,
                                                                         Pos   => Index));
            Index := Index + 1;
         end loop;
      end Skip;

   end White_Space;

   package body File_IO is

      procedure Create (Temporary_File : in out SPARK_IO.File_Type) is
         Unused : SPARK_IO.File_Status;
      begin
         --# accept Flow_Message, 10, Unused, "The variable Unused is not required" &
         --#        Flow_Message, 33, Unused, "The variable Unused is not required";
         SPARK_IO.Create (Temporary_File, 0, "", "", Unused);
         -- Not sure what we can do if we can't create a temporary file
      end Create;

      procedure Reset (Temporary_File : in out SPARK_IO.File_Type) is
         Unused : SPARK_IO.File_Status;
      begin
         --# accept Flow_Message, 10, Unused, "The variable Unused is not required" &
         --#        Flow_Message, 33, Unused, "The variable Unused is not required";
         SPARK_IO.Reset (Temporary_File, SPARK_IO.In_File, Unused);
         -- not sure what we can do if we can't reset the file
      end Reset;

      procedure Delete (Temporary_File : in out SPARK_IO.File_Type) is
         Unused : SPARK_IO.File_Status;
      begin
         --# accept Flow_Message, 10, Unused, "The variable Unused is not required" &
         --#        Flow_Message, 33, Unused, "The variable Unused is not required";
         SPARK_IO.Delete (Temporary_File, Unused);
         -- not sure what we can do if we can't delete the file
      end Delete;

      procedure Lex
        (Temporary_File : in     SPARK_IO.File_Type;
         Token          :    out SP_Symbols.SP_Terminal;
         Lex_Val        :    out LexTokenManager.Lex_Value)
      is
         Unused : Boolean;
      begin
         --# accept Flow_Message, 10, Unused, "The variable Unused is not required" &
         --#        Flow_Message, 33, Unused, "The variable Unused is not required";
         SparkLex.SPARK_Format_Lex (Prog_Text   => Temporary_File,
                                    Token       => Token,
                                    Lex_Val     => Lex_Val,
                                    Punct_Token => Unused);
      end Lex;

   end File_IO;

   procedure Copy (Input, Output : in SPARK_IO.File_Type) is
      Input_Line : E_Strings.T;
   begin
      while not SPARK_IO.End_Of_File (Input) loop
         E_Strings.Get_Line (File  => Input,
                             E_Str => Input_Line);
         E_Strings.Put_Line (File  => Output,
                             E_Str => Input_Line);
      end loop;
   end Copy;

   package body Iteration is separate;

   package body Annotations is separate;

   package body Reformatter is separate;

   procedure Reformat_Annotations (Input, Output : in SPARK_IO.File_Type) is

      type State_Type is (
                          Parsing_SPARK_Code,
                          Parsing_Globals_List,
                          Parsing_Derives_List,
                          Parsing_Inherit_Clause,
                          Parsing_Own_Variable_Clause,
                          Parsing_Refinement_Definition,
                          Parsing_Initialization_Specification);

      --# inherit Ada.Characters.Handling,
      --#         CommandLineData,
      --#         E_Strings,
      --#         SPARK_IO,
      --#         White_Space;
      package Annotation
      --# own Start_String;
      is

         procedure Initialize;
         --# global in     CommandLineData.Content;
         --#           out Start_String;
         --# derives Start_String from CommandLineData.Content;

         procedure Is_Start (Input_Line : in     E_Strings.T;
                             Index      : in out E_Strings.Lengths;
                             OK         :    out Boolean);
         --# global in Start_String;
         --# derives Index,
         --#         OK    from Index,
         --#                    Input_Line,
         --#                    Start_String;

         procedure Write (Output    : in SPARK_IO.File_Type;
                          Start_Col : in E_Strings.Positions);
         --# global in     Start_String;
         --#        in out SPARK_IO.File_Sys;
         --# derives SPARK_IO.File_Sys from *,
         --#                                Output,
         --#                                Start_Col,
         --#                                Start_String;

      end Annotation;

      --# inherit Ada.Characters.Handling,
      --#         Annotation,
      --#         E_Strings,
      --#         White_Space;
      package SPARK_Keyword_Matching is

         function Match
           (Input_Line    : E_Strings.T;
            Index         : E_Strings.Lengths;
            Match_Keyword : String)
           return          Boolean;

         function Match_At_Start (Input_Line    : E_Strings.T;
                                  Match_Keyword : String) return Boolean;
         --# global in Annotation.Start_String;

      end SPARK_Keyword_Matching;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package Accept_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end Accept_List;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package End_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end End_List;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package For_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end For_List;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package Function_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end Function_List;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package Type_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end Type_List;

      --# inherit Annotation,
      --#         E_Strings,
      --#         SPARK_Keyword_Matching,
      --#         White_Space;
      package Assert_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

      end Assert_List;

      --# inherit Ada.Characters.Handling,
      --#         Annotation,
      --#         CommandLineData,
      --#         Dictionary,
      --#         ErrorHandler,
      --#         E_Strings,
      --#         File_IO,
      --#         Heap,
      --#         LexTokenManager,
      --#         LexTokenManager.Relation_Algebra,
      --#         LexTokenManager.Relation_Algebra.String,
      --#         LexTokenManager.Seq_Algebra,
      --#         RelationAlgebra,
      --#         SeqAlgebra,
      --#         SparkFormatCommandLineData,
      --#         SparkLex,
      --#         SPARKProgram,
      --#         SPARK_IO,
      --#         SPARK_Keyword_Matching,
      --#         SP_Symbols,
      --#         Statistics,
      --#         White_Space;
      package Derives_List
      --# own State;
      is

         procedure Initialize;
         --# global in out LexTokenManager.State;
         --#           out State;
         --# derives LexTokenManager.State,
         --#         State                 from LexTokenManager.State;

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

         function Is_End (Input_Line : E_Strings.T) return Boolean;

         procedure Parse
           (Temporary_File : in out SPARK_IO.File_Type;
            Start_Col      :    out E_Strings.Positions;
            The_Heap       : in out Heap.HeapRecord;
            Imports        :    out LexTokenManager.Seq_Algebra.Seq;
            Exports        :    out LexTokenManager.Seq_Algebra.Seq;
            Dependencies   :    out LexTokenManager.Relation_Algebra.String.Relation;
            OK             :    out Boolean);
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     SparkFormatCommandLineData.Content;
         --#        in     State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#           out SparkLex.Curr_Line;
         --# derives Dependencies,
         --#         Exports,
         --#         Imports                    from The_Heap &
         --#         ErrorHandler.Error_Context,
         --#         LexTokenManager.State,
         --#         OK,
         --#         SparkLex.Curr_Line,
         --#         SPARK_IO.File_Sys,
         --#         The_Heap                   from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SparkFormatCommandLineData.Content,
         --#                                         SPARK_IO.File_Sys,
         --#                                         State,
         --#                                         Temporary_File,
         --#                                         The_Heap &
         --#         Start_Col                  from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File &
         --#         Statistics.TableUsage      from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SparkFormatCommandLineData.Content,
         --#                                         SPARK_IO.File_Sys,
         --#                                         State,
         --#                                         Temporary_File,
         --#                                         The_Heap &
         --#         Temporary_File             from *;

         procedure Reformat
           (OK             : in     Boolean;
            Temporary_File : in out SPARK_IO.File_Type;
            Output         : in     SPARK_IO.File_Type;
            Start_Col      : in     E_Strings.Positions;
            The_Heap       : in out Heap.HeapRecord;
            Exports        : in     LexTokenManager.Seq_Algebra.Seq;
            Dependencies   : in     LexTokenManager.Relation_Algebra.String.Relation);
         --# global in     Annotation.Start_String;
         --#        in     LexTokenManager.State;
         --#        in     SparkFormatCommandLineData.Content;
         --#        in     State;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --# derives SPARK_IO.File_Sys     from *,
         --#                                    Annotation.Start_String,
         --#                                    Dependencies,
         --#                                    Exports,
         --#                                    LexTokenManager.State,
         --#                                    OK,
         --#                                    Output,
         --#                                    SparkFormatCommandLineData.Content,
         --#                                    Start_Col,
         --#                                    State,
         --#                                    Temporary_File,
         --#                                    The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap              from *,
         --#                                    Dependencies,
         --#                                    Exports,
         --#                                    LexTokenManager.State,
         --#                                    OK,
         --#                                    SparkFormatCommandLineData.Content,
         --#                                    State,
         --#                                    The_Heap &
         --#         Temporary_File        from *,
         --#                                    OK;

      end Derives_List;

      package Subprogram is
         type Subprogram_Type is (Is_Function, Is_Procedure, Is_Unknown);
      end Subprogram;

      --# inherit Ada.Characters.Handling,
      --#         Annotation,
      --#         CommandLineData,
      --#         Derives_List,
      --#         Dictionary,
      --#         ErrorHandler,
      --#         E_Strings,
      --#         File_IO,
      --#         Heap,
      --#         LexTokenManager,
      --#         RelationAlgebra,
      --#         SeqAlgebra,
      --#         SparkFormatCommandLineData,
      --#         SparkLex,
      --#         SPARKProgram,
      --#         SPARK_IO,
      --#         SPARK_Keyword_Matching,
      --#         SP_Symbols,
      --#         Statistics,
      --#         Subprogram,
      --#         White_Space;
      package Declare_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

         function Is_End (Input_Line : E_Strings.T) return Boolean;
         pragma Unreferenced (Is_End); -- for future use

      end Declare_List;

      --# inherit Ada.Characters.Handling,
      --#         Annotation,
      --#         CommandLineData,
      --#         Derives_List,
      --#         Dictionary,
      --#         ErrorHandler,
      --#         E_Strings,
      --#         File_IO,
      --#         Heap,
      --#         LexTokenManager,
      --#         RelationAlgebra,
      --#         SeqAlgebra,
      --#         SparkFormatCommandLineData,
      --#         SparkLex,
      --#         SPARKProgram,
      --#         SPARK_IO,
      --#         SPARK_Keyword_Matching,
      --#         SP_Symbols,
      --#         Statistics,
      --#         Subprogram,
      --#         White_Space;
      package Proof_List is

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

         function Is_End (Input_Line : E_Strings.T) return Boolean;
         pragma Unreferenced (Is_End); -- for future use

      end Proof_List;

      --# inherit Accept_List,
      --#         Ada.Characters.Handling,
      --#         Annotation,
      --#         Assert_List,
      --#         CommandLineData,
      --#         Declare_List,
      --#         Derives_List,
      --#         Dictionary,
      --#         End_List,
      --#         ErrorHandler,
      --#         E_Strings,
      --#         File_IO,
      --#         For_List,
      --#         Function_List,
      --#         Heap,
      --#         LexTokenManager,
      --#         LexTokenManager.Seq_Algebra,
      --#         Proof_List,
      --#         RelationAlgebra,
      --#         SeqAlgebra,
      --#         SparkFormatCommandLineData,
      --#         SparkLex,
      --#         SPARKProgram,
      --#         SPARK_IO,
      --#         SPARK_Keyword_Matching,
      --#         SP_Symbols,
      --#         Statistics,
      --#         Subprogram,
      --#         Type_List,
      --#         White_Space;
      package Globals_List
      --# own Consecutive_Empty_Lines;
      --# initializes Consecutive_Empty_Lines;
      is

         type Modes is (Unmoded, In_Mode, In_Out_Mode, Out_Mode);
         type Global_Variables_Type is array (Modes) of LexTokenManager.Seq_Algebra.Seq;

         function Is_Start (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

         function Is_End (Input_Line : E_Strings.T) return Boolean;
         --# global in Annotation.Start_String;

         procedure Increment_Consecutive_Empty_Lines;
         --# global in out Consecutive_Empty_Lines;
         --# derives Consecutive_Empty_Lines from *;

         procedure Reset_Consecutive_Empty_Lines;
         --# global out Consecutive_Empty_Lines;
         --# derives Consecutive_Empty_Lines from ;

         function No_Empty_Lines return Boolean;
         --# global in Consecutive_Empty_Lines;

         procedure Parse
           (Temporary_File   : in out SPARK_IO.File_Type;
            Start_Col        :    out E_Strings.Positions;
            The_Heap         : in out Heap.HeapRecord;
            Global_Variables :    out Global_Variables_Type;
            OK               :    out Boolean);
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#           out SparkLex.Curr_Line;
         --# derives ErrorHandler.Error_Context,
         --#         LexTokenManager.State,
         --#         OK,
         --#         SparkLex.Curr_Line,
         --#         SPARK_IO.File_Sys,
         --#         Start_Col                  from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File &
         --#         Global_Variables           from The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap                   from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File,
         --#                                         The_Heap &
         --#         Temporary_File             from *;

         procedure Reformat
           (OK                    : in     Boolean;
            Temporary_File        : in out SPARK_IO.File_Type;
            Output                : in     SPARK_IO.File_Type;
            Start_Col             : in     E_Strings.Positions;
            The_Heap              : in out Heap.HeapRecord;
            Function_Or_Procedure : in     Subprogram.Subprogram_Type;
            Global_Variables      : in     Global_Variables_Type;
            Imports               : in     LexTokenManager.Seq_Algebra.Seq;
            Exports               : in     LexTokenManager.Seq_Algebra.Seq);
         --# global in     Annotation.Start_String;
         --#        in     LexTokenManager.State;
         --#        in     SparkFormatCommandLineData.Content;
         --#        in out Consecutive_Empty_Lines;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --# derives Consecutive_Empty_Lines from  &
         --#         SPARK_IO.File_Sys       from *,
         --#                                      Annotation.Start_String,
         --#                                      Consecutive_Empty_Lines,
         --#                                      Exports,
         --#                                      Function_Or_Procedure,
         --#                                      Global_Variables,
         --#                                      Imports,
         --#                                      LexTokenManager.State,
         --#                                      OK,
         --#                                      Output,
         --#                                      SparkFormatCommandLineData.Content,
         --#                                      Start_Col,
         --#                                      Temporary_File,
         --#                                      The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap                from *,
         --#                                      Exports,
         --#                                      Function_Or_Procedure,
         --#                                      Global_Variables,
         --#                                      Imports,
         --#                                      LexTokenManager.State,
         --#                                      OK,
         --#                                      SparkFormatCommandLineData.Content,
         --#                                      The_Heap &
         --#         Temporary_File          from *,
         --#                                      OK;

      end Globals_List;

      Function_Or_Procedure : Subprogram.Subprogram_Type;
      State                 : State_Type;
      Input_Line            : E_Strings.T;
      The_Heap              : Heap.HeapRecord;
      Globals_List_File     : SPARK_IO.File_Type;
      Derives_List_File     : SPARK_IO.File_Type;
      Inherit_Clause_File   : SPARK_IO.File_Type;
      Initialize_Spec_File  : SPARK_IO.File_Type;
      Own_Var_Clause_File   : SPARK_IO.File_Type;
      Global_Variables      : Globals_List.Global_Variables_Type;
      Imports               : LexTokenManager.Seq_Algebra.Seq;
      Exports               : LexTokenManager.Seq_Algebra.Seq;
      Dependencies          : LexTokenManager.Relation_Algebra.String.Relation;
      Start_Col             : E_Strings.Positions;
      Globals_List_OK       : Boolean;
      Derives_List_OK       : Boolean;
      Inherit_Anno          : Annotations.Anno_Type;
      Initializes_Anno      : Annotations.Anno_Type;
      Own_Var_Anno          : Annotations.Anno_Type;
      Inherit_Clause        : Reformatter.State;
      Initialization_Spec   : Reformatter.State;
      Own_Variable_Clause   : Reformatter.State;
      File_IO_Required      : Boolean;
      Reformat_Successful   : Boolean;

      package body Annotation is

         Start_String : E_Strings.T;

         procedure Initialize is
         begin
            Start_String := E_Strings.Copy_String (Str => "--");
            E_Strings.Append_Char (E_Str => Start_String,
                                   Ch    => CommandLineData.Content.Anno_Char);
         end Initialize;

         procedure Is_Start (Input_Line : in     E_Strings.T;
                             Index      : in out E_Strings.Lengths;
                             OK         :    out Boolean) is
         begin

            White_Space.Skip (Input_Line => Input_Line,
                              Index      => Index);

            if E_Strings.Get_Length (E_Str => Input_Line) - Index >= 2 then
               if E_Strings.Get_Element (E_Str => Input_Line,
                                         Pos   => Index) =
                 E_Strings.Get_Element (E_Str => Start_String,
                                        Pos   => 1)
                 and then E_Strings.Get_Element (E_Str => Input_Line,
                                                 Pos   => Index + 1) =
                 E_Strings.Get_Element (E_Str => Start_String,
                                        Pos   => 2)
                 and then E_Strings.Get_Element (E_Str => Input_Line,
                                                 Pos   => Index + 2) =
                 E_Strings.Get_Element (E_Str => Start_String,
                                        Pos   => 3) then
                  Index := Index + 3;
                  OK    := True;
               else
                  OK := False;
               end if;
            else
               OK := False;
            end if;

         end Is_Start;

         procedure Write (Output    : in SPARK_IO.File_Type;
                          Start_Col : in E_Strings.Positions) is
         begin
            SPARK_IO.Set_Col (Output, Start_Col);
            E_Strings.Put_String (File  => Output,
                                  E_Str => Start_String);
         end Write;

      end Annotation;

      package body SPARK_Keyword_Matching is

         -- Input_Line    - A line from the spark input file.
         -- Index        - An index position, expected to inside Input_Line.
         -- Match_Keyword - A keyword to match.
         --
         -- The function returns true where Input_Line, at position index, contains
         -- the keyword Match_Keyword. For a match, the keyword must be terminated
         -- by a newline or white space.
         function Match
           (Input_Line    : E_Strings.T;
            Index         : E_Strings.Lengths;
            Match_Keyword : String)
           return          Boolean
         is
            Is_Match          : Boolean;
            Char_From_Line    : Character;
            Char_From_Keyword : Character;
         begin

            -- E_Strings.Lengths'First is zero. This is used to describe empty strings.
            -- Can not find a match against an empty string.
            if Index = E_Strings.Lengths'First then
               Is_Match := False;
            else
               Is_Match := True;
               for I in E_Strings.Lengths range 1 .. Match_Keyword'Length loop
                  if (Index - 1) + I >= (E_Strings.Get_Length (E_Str => Input_Line) + 1) then
                     -- Reached or exceeded the end of line. Can not be a match.
                     Is_Match := False;
                     exit;
                  end if;

                  --# assert Match_Keyword=Match_Keyword% and
                  --#   Index > E_Strings.Lengths'First and
                  --#   Index <= E_Strings.Lengths'Last and
                  --#   I>=1 and I<=Match_Keyword'Length and
                  --#   (((Index - 1) + I) >= E_Strings.Lengths'First) and
                  --#   (((Index - 1) + I) <= E_Strings.Lengths'Last);

                  Char_From_Line    :=
                    Ada.Characters.Handling.To_Lower (E_Strings.Get_Element (E_Str => Input_Line,
                                                                             Pos   => (Index - 1) + I));
                  Char_From_Keyword := Ada.Characters.Handling.To_Lower (Match_Keyword (I));
                  if not (Char_From_Line = Char_From_Keyword) then
                     -- Are not the same at this index. Can not be a match.
                     Is_Match := False;
                     exit;
                  end if;
               end loop;

               -- If detected a keyword match, then investigate what appears after
               -- the keyword.
               if Is_Match then
                  -- If not terminated by line feed, is only a match if followed by
                  -- white space.
                  if ((Index + Match_Keyword'Length) <= E_Strings.Get_Length (E_Str => Input_Line)) then
                     Is_Match :=
                       White_Space.Is_White_Space
                       (Char => E_Strings.Get_Element (E_Str => Input_Line,
                                                       Pos   => Index + Match_Keyword'Length));
                  end if;
               end if;
            end if;

            return Is_Match;
         end Match;

         -- Input_Line    - A line from the spark input file.
         -- Match_Keyword - A sparkkwyword to match.
         --
         -- The function returns true where Input_Line is an annotation line, starting
         -- with the keyword Match_Keyword.
         function Match_At_Start (Input_Line    : E_Strings.T;
                                  Match_Keyword : String) return Boolean is
            Index : E_Strings.Lengths;
            OK    : Boolean;
         begin
            if E_Strings.Get_Length (E_Str => Input_Line) > 0 then
               Index := 1;
               Annotation.Is_Start (Input_Line => Input_Line,
                                    Index      => Index,
                                    OK         => OK);
               if OK then
                  White_Space.Skip (Input_Line => Input_Line,
                                    Index      => Index);
                  OK := Match (Input_Line, Index, Match_Keyword);
               end if;
            else
               OK := False;
            end if;

            return OK;
         end Match_At_Start;

      end SPARK_Keyword_Matching;

      package body Accept_List is

         Keyword : constant String := "accept";

         -- checks it's at the start of a line up to "--# accept"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end Accept_List;

      package body End_List is

         Keyword : constant String := "end";

         -- checks it's at the start of a line up to "--# end"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end End_List;

      package body For_List is

         Keyword : constant String := "for";

         -- checks it's at the start of a line up to "--# for"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end For_List;

      package body Function_List is

         Keyword : constant String := "function";

         -- checks it's at the start of a line up to "--# function"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end Function_List;

      package body Type_List is

         Keyword : constant String := "type";

         -- checks it's at the start of a line up to "--# type"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end Type_List;

      package body Assert_List is

         Keyword : constant String := "assert";

         -- checks it's at the start of a line up to "--# assert"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

      end Assert_List;

      package body Derives_List
      --# own State is Multiply_Token,
      --#              RW_Null_Token;
      is

         Keyword : constant String := "derives";

         Multiply_Token, RW_Null_Token : LexTokenManager.Lex_String;

         procedure Initialize
         --# global in out LexTokenManager.State;
         --#           out Multiply_Token;
         --#           out RW_Null_Token;
         --# derives LexTokenManager.State,
         --#         Multiply_Token,
         --#         RW_Null_Token         from LexTokenManager.State;
         is
         begin
            LexTokenManager.Insert_Examiner_String (Str     => E_Strings.Copy_String (Str => "*"),
                                                    Lex_Str => Multiply_Token);
            LexTokenManager.Insert_Examiner_String (Str     => E_Strings.Copy_String (Str => "null"),
                                                    Lex_Str => RW_Null_Token);

         end Initialize;

         -- checks it's at the start of a line up to "--# derives"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

         -- checks for ";" at end of line
         function Is_End (Input_Line : E_Strings.T) return Boolean is
            Result : Boolean;
         begin

            Result := False;

            for I in E_Strings.Lengths range E_Strings.Positions'First .. E_Strings.Get_Length (E_Str => Input_Line) loop
               if E_Strings.Get_Element (E_Str => Input_Line,
                                         Pos   => I) = ';' then
                  Result := True;
                  exit;
               end if;
            end loop;

            return Result;

         end Is_End;

         procedure Parse
           (Temporary_File : in out SPARK_IO.File_Type;
            Start_Col      :    out E_Strings.Positions;
            The_Heap       : in out Heap.HeapRecord;
            Imports        :    out LexTokenManager.Seq_Algebra.Seq;
            Exports        :    out LexTokenManager.Seq_Algebra.Seq;
            Dependencies   :    out LexTokenManager.Relation_Algebra.String.Relation;
            OK             :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     Multiply_Token;
         --#        in     RW_Null_Token;
         --#        in     SparkFormatCommandLineData.Content;
         --#        in out ErrorHandler.Error_Context;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#           out SparkLex.Curr_Line;
         --# derives Dependencies,
         --#         Exports,
         --#         Imports                    from The_Heap &
         --#         ErrorHandler.Error_Context,
         --#         LexTokenManager.State,
         --#         OK,
         --#         SparkLex.Curr_Line,
         --#         SPARK_IO.File_Sys,
         --#         The_Heap                   from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         Multiply_Token,
         --#                                         RW_Null_Token,
         --#                                         SparkFormatCommandLineData.Content,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File,
         --#                                         The_Heap &
         --#         Start_Col                  from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File &
         --#         Statistics.TableUsage      from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         Multiply_Token,
         --#                                         RW_Null_Token,
         --#                                         SparkFormatCommandLineData.Content,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Temporary_File,
         --#                                         The_Heap &
         --#         Temporary_File             from *;
         is

            Token   : SP_Symbols.SP_Terminal;
            Lex_Val : LexTokenManager.Lex_Value;

            procedure Parse_Dependency_Clauses
              (Temporary_File : in     SPARK_IO.File_Type;
               Token          : in out SP_Symbols.SP_Terminal;
               Lex_Val        : in     LexTokenManager.Lex_Value;
               The_Heap       : in out Heap.HeapRecord;
               Exports        : in     LexTokenManager.Seq_Algebra.Seq;
               Imports        : in     LexTokenManager.Seq_Algebra.Seq;
               Dependencies   : in     LexTokenManager.Relation_Algebra.String.Relation;
               OK             :    out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     Multiply_Token;
            --#        in     RW_Null_Token;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out ErrorHandler.Error_Context;
            --#        in out LexTokenManager.State;
            --#        in out SparkLex.Curr_Line;
            --#        in out SPARK_IO.File_Sys;
            --#        in out Statistics.TableUsage;
            --# derives ErrorHandler.Error_Context,
            --#         LexTokenManager.State,
            --#         SparkLex.Curr_Line,
            --#         SPARK_IO.File_Sys,
            --#         Statistics.TableUsage,
            --#         The_Heap,
            --#         Token                      from *,
            --#                                         CommandLineData.Content,
            --#                                         Dependencies,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Exports,
            --#                                         Imports,
            --#                                         LexTokenManager.State,
            --#                                         Lex_Val,
            --#                                         Multiply_Token,
            --#                                         RW_Null_Token,
            --#                                         SparkFormatCommandLineData.Content,
            --#                                         SparkLex.Curr_Line,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Temporary_File,
            --#                                         The_Heap,
            --#                                         Token &
            --#         OK                         from CommandLineData.Content,
            --#                                         Dependencies,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Exports,
            --#                                         Imports,
            --#                                         LexTokenManager.State,
            --#                                         Lex_Val,
            --#                                         Multiply_Token,
            --#                                         RW_Null_Token,
            --#                                         SparkFormatCommandLineData.Content,
            --#                                         SparkLex.Curr_Line,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Temporary_File,
            --#                                         The_Heap,
            --#                                         Token;
            is

               Similar_Exports         : LexTokenManager.Seq_Algebra.Seq;
               Imports_For_This_Export : LexTokenManager.Seq_Algebra.Seq;
               Next_Lex_Val            : LexTokenManager.Lex_Value;
               Some_Exports            : Boolean;

               procedure Parse_Export_List
                 (Temporary_File  : in     SPARK_IO.File_Type;
                  Token           : in out SP_Symbols.SP_Terminal;
                  Lex_Val         : in out LexTokenManager.Lex_Value;
                  The_Heap        : in out Heap.HeapRecord;
                  Exports         : in     LexTokenManager.Seq_Algebra.Seq;
                  Similar_Exports : in     LexTokenManager.Seq_Algebra.Seq;
                  OK              :    out Boolean)
               --# global in     CommandLineData.Content;
               --#        in     Dictionary.Dict;
               --#        in     RW_Null_Token;
               --#        in     SparkFormatCommandLineData.Content;
               --#        in out ErrorHandler.Error_Context;
               --#        in out LexTokenManager.State;
               --#        in out SparkLex.Curr_Line;
               --#        in out SPARK_IO.File_Sys;
               --#        in out Statistics.TableUsage;
               --# derives ErrorHandler.Error_Context,
               --#         LexTokenManager.State,
               --#         Lex_Val,
               --#         OK,
               --#         SparkLex.Curr_Line,
               --#         SPARK_IO.File_Sys,
               --#         Token                      from CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         SparkFormatCommandLineData.Content,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         Token &
               --#         Statistics.TableUsage,
               --#         The_Heap                   from *,
               --#                                         CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         Exports,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         RW_Null_Token,
               --#                                         Similar_Exports,
               --#                                         SparkFormatCommandLineData.Content,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         The_Heap,
               --#                                         Token;
               is
                  Dotted_Simple_Name  : E_Strings.T;
                  Export              : LexTokenManager.Lex_String;
                  No_Exports_Excluded : Boolean;
               begin

                  OK := True;

                  --  CFR1753: Check to see if an export has been excluded.
                  No_Exports_Excluded := E_Strings.Is_Empty (E_Str => SparkFormatCommandLineData.Content.Exclude_Export);

                  case Token is
                     when SP_Symbols.identifier =>
                        loop
                           Dotted_Simple_Name := LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str);
                           File_IO.Lex (Temporary_File => Temporary_File,
                                        Token          => Token,
                                        Lex_Val        => Lex_Val);
                           loop
                              exit when Token /= SP_Symbols.point;
                              E_Strings.Append_String (E_Str => Dotted_Simple_Name,
                                                       Str   => ".");
                              File_IO.Lex (Temporary_File => Temporary_File,
                                           Token          => Token,
                                           Lex_Val        => Lex_Val);
                              if Token = SP_Symbols.identifier then
                                 E_Strings.Append_Examiner_String
                                   (E_Str1 => Dotted_Simple_Name,
                                    E_Str2 => LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str));
                                 File_IO.Lex (Temporary_File => Temporary_File,
                                              Token          => Token,
                                              Lex_Val        => Lex_Val);
                              else
                                 OK := False;
                              end if;
                              exit when not OK;
                           end loop;
                           exit when not OK;

                           --  CFR 1753: Check to see if this export has to be
                           --  excluded.
                           if No_Exports_Excluded
                             or else not E_Strings.Eq_String
                             (E_Str1 => Dotted_Simple_Name,
                              E_Str2 => SparkFormatCommandLineData.Content.Exclude_Export) then
                              LexTokenManager.Insert_Examiner_String (Str     => Dotted_Simple_Name,
                                                                      Lex_Str => Export);
                              LexTokenManager.Seq_Algebra.Add_Member (The_Heap    => The_Heap,
                                                                      S           => Exports,
                                                                      Given_Value => Export);
                              LexTokenManager.Seq_Algebra.Add_Member
                                (The_Heap    => The_Heap,
                                 S           => Similar_Exports,
                                 Given_Value => Export);
                           end if;
                           exit when Token = SP_Symbols.RWfrom;
                           if Token = SP_Symbols.comma then
                              File_IO.Lex (Temporary_File => Temporary_File,
                                           Token          => Token,
                                           Lex_Val        => Lex_Val);
                              if Token /= SP_Symbols.identifier then
                                 OK := False;
                              end if;
                           else
                              OK := False;
                           end if;
                           exit when not OK;
                        end loop;
                     when SP_Symbols.RWnull =>
                        LexTokenManager.Seq_Algebra.Add_Member (The_Heap    => The_Heap,
                                                                S           => Exports,
                                                                Given_Value => RW_Null_Token);
                        LexTokenManager.Seq_Algebra.Add_Member
                          (The_Heap    => The_Heap,
                           S           => Similar_Exports,
                           Given_Value => RW_Null_Token);
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Lex_Val);
                     when SP_Symbols.semicolon =>
                        null;
                     when others =>
                        OK := False;
                  end case;

               end Parse_Export_List;

               procedure Parse_Import_List
                 (Temporary_File          : in     SPARK_IO.File_Type;
                  Token                   : in out SP_Symbols.SP_Terminal;
                  Lex_Val                 : in out LexTokenManager.Lex_Value;
                  The_Heap                : in out Heap.HeapRecord;
                  Similar_Exports         : in     LexTokenManager.Seq_Algebra.Seq;
                  Imports                 : in     LexTokenManager.Seq_Algebra.Seq;
                  Imports_For_This_Export : in     LexTokenManager.Seq_Algebra.Seq;
                  OK                      :    out Boolean)
               --# global in     CommandLineData.Content;
               --#        in     Dictionary.Dict;
               --#        in     Multiply_Token;
               --#        in out ErrorHandler.Error_Context;
               --#        in out LexTokenManager.State;
               --#        in out SparkLex.Curr_Line;
               --#        in out SPARK_IO.File_Sys;
               --#        in out Statistics.TableUsage;
               --# derives ErrorHandler.Error_Context,
               --#         LexTokenManager.State,
               --#         Lex_Val,
               --#         OK,
               --#         SparkLex.Curr_Line,
               --#         SPARK_IO.File_Sys,
               --#         Token                      from CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         Similar_Exports,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         The_Heap,
               --#                                         Token &
               --#         Statistics.TableUsage,
               --#         The_Heap                   from *,
               --#                                         CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         Imports,
               --#                                         Imports_For_This_Export,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         Multiply_Token,
               --#                                         Similar_Exports,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         The_Heap,
               --#                                         Token;
               is
                  Dotted_Simple_Name : E_Strings.T;
                  Export             : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Import_Name        : LexTokenManager.Lex_String;
                  Some_Exports       : Boolean;
               begin

                  OK := True;

                  --  CFR1753: There may be no exports in the export list if an
                  --  excluded export was the only variable in the list.
                  Some_Exports := not LexTokenManager.Seq_Algebra.Is_Empty_Seq (The_Heap => The_Heap,
                                                                                S        => Similar_Exports);
                  loop
                     exit when Token = SP_Symbols.semicolon or Token = SP_Symbols.ampersand;
                     case Token is
                        when SP_Symbols.identifier =>
                           Dotted_Simple_Name := LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str);
                           File_IO.Lex (Temporary_File => Temporary_File,
                                        Token          => Token,
                                        Lex_Val        => Lex_Val);
                           loop
                              exit when Token /= SP_Symbols.point;
                              E_Strings.Append_String (E_Str => Dotted_Simple_Name,
                                                       Str   => ".");
                              File_IO.Lex (Temporary_File => Temporary_File,
                                           Token          => Token,
                                           Lex_Val        => Lex_Val);
                              if Token = SP_Symbols.identifier then
                                 E_Strings.Append_Examiner_String
                                   (E_Str1 => Dotted_Simple_Name,
                                    E_Str2 => LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str));
                                 File_IO.Lex (Temporary_File => Temporary_File,
                                              Token          => Token,
                                              Lex_Val        => Lex_Val);
                              else
                                 OK := False;
                              end if;
                              exit when not OK;
                           end loop;
                           --  CFR1753: Ensure that the export list is non-empty
                           --  Otherwise do not add imports to the import sets.
                           if OK and Some_Exports then
                              LexTokenManager.Insert_Examiner_String (Str     => Dotted_Simple_Name,
                                                                      Lex_Str => Import_Name);
                              LexTokenManager.Seq_Algebra.Add_Member
                                (The_Heap    => The_Heap,
                                 S           => Imports,
                                 Given_Value => Import_Name);
                              LexTokenManager.Seq_Algebra.Add_Member
                                (The_Heap    => The_Heap,
                                 S           => Imports_For_This_Export,
                                 Given_Value => Import_Name);
                           end if;
                        when SP_Symbols.multiply =>
                           --  CFR1753: Ensure that the export list is non-empty
                           --  Otherwise do not add imports to the import sets.
                           --# accept F, 41, "Used to simplify loop structure";
                           if Some_Exports then
                              Export := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                                  S        => Similar_Exports);
                              loop
                                 exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Export);
                                 LexTokenManager.Seq_Algebra.Add_Member
                                   (The_Heap    => The_Heap,
                                    S           => Imports,
                                    Given_Value => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                                M        => Export));
                                 Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                    M        => Export);
                              end loop;
                              LexTokenManager.Seq_Algebra.Add_Member
                                (The_Heap    => The_Heap,
                                 S           => Imports_For_This_Export,
                                 Given_Value => Multiply_Token);
                              --  else
                              --     SPARK_IO.Put_Line (SPARK_IO.Standard_Output,
                              --        "ParseImporList: No exports discarding *",
                              --        0);
                           end if;
                           --# end accept;
                           File_IO.Lex (Temporary_File => Temporary_File,
                                        Token          => Token,
                                        Lex_Val        => Lex_Val);
                        when SP_Symbols.comma =>
                           null;
                        when others =>
                           OK := False;
                     end case;
                     exit when not OK or Token = SP_Symbols.semicolon or Token = SP_Symbols.ampersand;
                     if Token = SP_Symbols.comma then
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Lex_Val);
                     else
                        OK := False;
                     end if;
                  end loop;

               end Parse_Import_List;

               procedure Store_Dependencies
                 (The_Heap     : in out Heap.HeapRecord;
                  Exports      : in     LexTokenManager.Seq_Algebra.Seq;
                  Imports      : in     LexTokenManager.Seq_Algebra.Seq;
                  Dependencies : in     LexTokenManager.Relation_Algebra.String.Relation)
               --# global in     LexTokenManager.State;
               --#        in     Multiply_Token;
               --#        in out Statistics.TableUsage;
               --# derives Statistics.TableUsage,
               --#         The_Heap              from *,
               --#                                    Dependencies,
               --#                                    Exports,
               --#                                    Imports,
               --#                                    LexTokenManager.State,
               --#                                    Multiply_Token,
               --#                                    The_Heap;
               is
                  Export, Import         : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Export_Val, Import_Val : LexTokenManager.Lex_String;
               begin
                  Export := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                      S        => Exports);
                  loop
                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Export);
                     Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                M        => Export);
                     Import     := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                             S        => Imports);
                     loop
                        exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Import);
                        Import_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                   M        => Import);
                        if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Export_Val,
                                                                                Lex_Str2 => Import_Val) =
                          LexTokenManager.Str_Eq then
                           Import_Val := Multiply_Token;
                        end if;
                        LexTokenManager.Relation_Algebra.String.Insert_Pair
                          (The_Heap => The_Heap,
                           R        => Dependencies,
                           I        => Export_Val,
                           J        => Import_Val);
                        Import := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                           M        => Import);
                     end loop;
                     Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                        M        => Export);
                  end loop;
               end Store_Dependencies;

            begin

               OK           := True;
               Next_Lex_Val := Lex_Val;

               loop
                  exit when Token = SP_Symbols.semicolon;
                  LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                          S        => Similar_Exports);
                  Parse_Export_List
                    (Temporary_File  => Temporary_File,
                     Token           => Token,
                     Lex_Val         => Next_Lex_Val,
                     The_Heap        => The_Heap,
                     Exports         => Exports,
                     Similar_Exports => Similar_Exports,
                     OK              => OK);
                  if OK then
                     --  CFR1753: There may be no exports in the export list if an
                     --  excluded export was the only variable in the list,
                     --  however, we still need to parse the input list.
                     Some_Exports := not LexTokenManager.Seq_Algebra.Is_Empty_Seq (The_Heap => The_Heap,
                                                                                   S        => Similar_Exports);
                     if Token = SP_Symbols.RWfrom then
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Next_Lex_Val);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Imports_For_This_Export);
                        Parse_Import_List
                          (Temporary_File          => Temporary_File,
                           Token                   => Token,
                           Lex_Val                 => Next_Lex_Val,
                           The_Heap                => The_Heap,
                           Similar_Exports         => Similar_Exports,
                           Imports                 => Imports,
                           Imports_For_This_Export => Imports_For_This_Export,
                           OK                      => OK);
                        --  CFR1753: Only add imports and store the dependencies
                        --  if there are some exported variables associated
                        --  this import list.
                        if Some_Exports then
                           LexTokenManager.Seq_Algebra.Augment_Seq
                             (The_Heap => The_Heap,
                              A        => Imports,
                              B        => Imports_For_This_Export);
                           Store_Dependencies
                             (The_Heap     => The_Heap,
                              Exports      => Similar_Exports,
                              Imports      => Imports_For_This_Export,
                              Dependencies => Dependencies);
                        end if;
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Imports_For_This_Export);
                        if OK then
                           case Token is
                              when SP_Symbols.ampersand =>
                                 File_IO.Lex (Temporary_File => Temporary_File,
                                              Token          => Token,
                                              Lex_Val        => Next_Lex_Val);
                              when SP_Symbols.semicolon =>
                                 null;
                              when others =>
                                 OK := False;
                           end case;
                        end if;
                     else
                        OK := False;
                     end if;
                  end if;
                  LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                              S        => Similar_Exports);
                  exit when not OK;
               end loop;

            end Parse_Dependency_Clauses;

         begin

            File_IO.Reset (Temporary_File => Temporary_File);
            SparkLex.Clear_Line_Context;
            LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                    S        => Exports);
            LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                    S        => Imports);
            LexTokenManager.Relation_Algebra.String.Create_Relation (The_Heap => The_Heap,
                                                                     R        => Dependencies);
            File_IO.Lex (Temporary_File => Temporary_File,
                         Token          => Token,
                         Lex_Val        => Lex_Val);

            if Token = SP_Symbols.annotation_start then
               Start_Col := Lex_Val.Position.Start_Pos;
               -- we know Start_Col can't be zero because the line can't be empty
               --# accept Flow_Message, 10, Lex_Val, "The next symbol should be 'derives', so we don't need the Lex_Val";
               File_IO.Lex (Temporary_File => Temporary_File,
                            Token          => Token,
                            Lex_Val        => Lex_Val);
               --# end accept;
               if Token = SP_Symbols.RWderives then
                  File_IO.Lex (Temporary_File => Temporary_File,
                               Token          => Token,
                               Lex_Val        => Lex_Val);
                  Parse_Dependency_Clauses
                    (Temporary_File => Temporary_File,
                     Token          => Token,
                     Lex_Val        => Lex_Val,
                     The_Heap       => The_Heap,
                     Exports        => Exports,
                     Imports        => Imports,
                     Dependencies   => Dependencies,
                     OK             => OK);
                  OK := OK and Token = SP_Symbols.semicolon;
               else
                  OK := False;
               end if;
            else
               OK := False;
            end if;
            --# accept Flow_Message, 602, Start_Col, Start_Col, "Start_Col may not be set if not OK";
         end Parse;

         procedure Reformat
           (OK             : in     Boolean;
            Temporary_File : in out SPARK_IO.File_Type;
            Output         : in     SPARK_IO.File_Type;
            Start_Col      : in     E_Strings.Positions;
            The_Heap       : in out Heap.HeapRecord;
            Exports        : in     LexTokenManager.Seq_Algebra.Seq;
            Dependencies   : in     LexTokenManager.Relation_Algebra.String.Relation)
         --# global in     Annotation.Start_String;
         --#        in     LexTokenManager.State;
         --#        in     Multiply_Token;
         --#        in     RW_Null_Token;
         --#        in     SparkFormatCommandLineData.Content;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --# derives SPARK_IO.File_Sys     from *,
         --#                                    Annotation.Start_String,
         --#                                    Dependencies,
         --#                                    Exports,
         --#                                    LexTokenManager.State,
         --#                                    Multiply_Token,
         --#                                    OK,
         --#                                    Output,
         --#                                    RW_Null_Token,
         --#                                    SparkFormatCommandLineData.Content,
         --#                                    Start_Col,
         --#                                    Temporary_File,
         --#                                    The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap              from *,
         --#                                    Dependencies,
         --#                                    Exports,
         --#                                    LexTokenManager.State,
         --#                                    Multiply_Token,
         --#                                    OK,
         --#                                    RW_Null_Token,
         --#                                    SparkFormatCommandLineData.Content,
         --#                                    The_Heap &
         --#         Temporary_File        from *,
         --#                                    OK;
         is

            First_Export : Boolean;
            Export_Width : E_Strings.Lengths;

            function Derives_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions is
            begin
               return Start_Col + 4; -- length of "--# "
            end Derives_Col;

            -- writes "derives " in correct position
            procedure Write_Derives (Output    : in SPARK_IO.File_Type;
                                     Start_Col : in E_Strings.Positions)
            --# global in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives SPARK_IO.File_Sys from *,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col;
            is
            begin
               SPARK_IO.Set_Col (Output, Derives_Col (Start_Col => Start_Col));
               SPARK_IO.Put_String (Output, "derives", 0);
               -- If ExportIndent is not Inline, then don't put out a trailing space,
               -- since this will be rejected by GNAT -gnatyb style check mode.
               if SparkFormatCommandLineData.Content.Export_Indent = SparkFormatCommandLineData.Inline then
                  SPARK_IO.Put_String (Output, " ", 0);
               end if;
            end Write_Derives;

            function Export_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions
            --# global in SparkFormatCommandLineData.Content;
            is
               Export_Column : E_Strings.Positions;
            begin
               if SparkFormatCommandLineData.Content.Export_Indent = SparkFormatCommandLineData.Inline then
                  Export_Column := Derives_Col (Start_Col => Start_Col) + 8; -- length of "derives "
               else
                  Export_Column := Derives_Col (Start_Col => Start_Col) +
                    (SparkFormatCommandLineData.Content.Export_Indent - 1);
               end if;
               return Export_Column;
            end Export_Col;

            -- only called when there is a value for separator indent, returns starting column
            function Separator_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions
            --# global in SparkFormatCommandLineData.Content;
            is
            begin
               -- Start_Col "is --# " but indent value is given from "--#"
               return Derives_Col (Start_Col => Start_Col) + (SparkFormatCommandLineData.Content.Separator_Indent - 1);
            end Separator_Col;

            procedure Write_Export
              (First_Export : in out Boolean;
               Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               The_Heap     : in     Heap.HeapRecord;
               Export       : in     LexTokenManager.Seq_Algebra.Member_Of_Seq)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives First_Export      from * &
            --#         SPARK_IO.File_Sys from *,
            --#                                Annotation.Start_String,
            --#                                Export,
            --#                                First_Export,
            --#                                LexTokenManager.State,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col,
            --#                                The_Heap;
            is
            begin
               if First_Export then
                  First_Export := False;
                  if SparkFormatCommandLineData.Content.Export_Indent /= SparkFormatCommandLineData.Inline then
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                  end if;
               else
                  if SparkFormatCommandLineData.Content.Separator_Indent = SparkFormatCommandLineData.Inline then
                     SPARK_IO.Put_Line (Output, " &", 0);
                  else
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                     SPARK_IO.Set_Col (Output, Separator_Col (Start_Col => Start_Col));
                     SPARK_IO.Put_Line (Output, "&", 0);
                  end if;
                  Annotation.Write (Output    => Output,
                                    Start_Col => Start_Col);
               end if;
               SPARK_IO.Set_Col (Output, Export_Col (Start_Col => Start_Col));
               E_Strings.Put_String
                 (File  => Output,
                  E_Str => LexTokenManager.Lex_String_To_String
                    (Lex_Str => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                             M        => Export)));
            end Write_Export;

            function Longest_Export
              (The_Heap : Heap.HeapRecord;
               Exports  : LexTokenManager.Seq_Algebra.Seq)
              return     E_Strings.Lengths
            --# global in LexTokenManager.State;
            is
               Max_Length : Natural;
               Export     : LexTokenManager.Seq_Algebra.Member_Of_Seq;

               function Max (A, B : Natural) return Natural is
                  Result : Natural;
               begin

                  if A >= B then
                     Result := A;
                  else
                     Result := B;
                  end if;

                  return Result;

               end Max;

            begin
               Max_Length := 0;
               Export     := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                       S        => Exports);
               loop
                  exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Export);
                  Max_Length :=
                    Max
                    (A => Max_Length,
                     B => E_Strings.Get_Length
                       (E_Str => LexTokenManager.Lex_String_To_String
                          (Lex_Str => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                   M        => Export))));
                  Export     := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                         M        => Export);
               end loop;
               return Max_Length;
            end Longest_Export;

            function From_Col (Start_Col    : E_Strings.Positions;
                               Export_Width : E_Strings.Lengths) return E_Strings.Positions
            --# global in SparkFormatCommandLineData.Content;
            is
               From_Column : E_Strings.Positions;
            begin
               if SparkFormatCommandLineData.Content.Separator_Indent = SparkFormatCommandLineData.Inline then
                  From_Column := (Export_Col (Start_Col => Start_Col) + Export_Width) + 1;
               else
                  From_Column := Separator_Col (Start_Col => Start_Col);
               end if;
               return From_Column;
            end From_Col;

            procedure Write_From
              (Output       : in SPARK_IO.File_Type;
               Start_Col    : in E_Strings.Positions;
               Export_Width : in E_Strings.Lengths)
            --# global in     Annotation.Start_String;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives SPARK_IO.File_Sys from *,
            --#                                Annotation.Start_String,
            --#                                Export_Width,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col;
            is
            begin
               if SparkFormatCommandLineData.Content.Separator_Indent /= SparkFormatCommandLineData.Inline then
                  Annotation.Write (Output    => Output,
                                    Start_Col => Start_Col);
               end if;
               SPARK_IO.Set_Col (Output, From_Col (Start_Col    => Start_Col,
                                                   Export_Width => Export_Width));
               SPARK_IO.Put_String (Output, "from", 0);
               -- If ImportIndent is not Inline, then don't put out a trailing space,
               -- since this will be rejected by GNAT -gnatyb style check mode.
               if SparkFormatCommandLineData.Content.Import_Indent = SparkFormatCommandLineData.Inline then
                  SPARK_IO.Put_String (Output, " ", 0);
               end if;
            end Write_From;

            procedure Write_Import
              (First_Import : in out Boolean;
               Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               Export_Width : in     E_Strings.Lengths;
               The_Heap     : in     Heap.HeapRecord;
               Import       : in     LexTokenManager.Seq_Algebra.Member_Of_Seq)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives First_Import      from * &
            --#         SPARK_IO.File_Sys from *,
            --#                                Annotation.Start_String,
            --#                                Export_Width,
            --#                                First_Import,
            --#                                Import,
            --#                                LexTokenManager.State,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col,
            --#                                The_Heap;
            is

               function Import_Col
                 (Start_Col    : E_Strings.Positions;
                  Export_Width : E_Strings.Lengths)
                 return         E_Strings.Positions
               --# global in SparkFormatCommandLineData.Content;
               is
                  Import_Column : E_Strings.Positions;
               begin
                  if SparkFormatCommandLineData.Content.Import_Indent = SparkFormatCommandLineData.Inline then
                     Import_Column := From_Col (Start_Col    => Start_Col,
                                                Export_Width => Export_Width) + 5; -- length of "from "
                  else
                     Import_Column := Derives_Col (Start_Col => Start_Col) +
                       (SparkFormatCommandLineData.Content.Import_Indent - 1);
                  end if;
                  return Import_Column;
               end Import_Col;

            begin

               if First_Import then
                  First_Import := False;
                  if SparkFormatCommandLineData.Content.Import_Indent /= SparkFormatCommandLineData.Inline then
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                  end if;
               else
                  SPARK_IO.Put_Line (Output, ",", 0);
                  Annotation.Write (Output    => Output,
                                    Start_Col => Start_Col);
               end if;

               SPARK_IO.Set_Col (Output, Import_Col (Start_Col    => Start_Col,
                                                     Export_Width => Export_Width));
               E_Strings.Put_String
                 (File  => Output,
                  E_Str => LexTokenManager.Lex_String_To_String
                    (Lex_Str => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                             M        => Import)));
            end Write_Import;

            procedure Write_Imports
              (Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               Export_Width : in     E_Strings.Lengths;
               The_Heap     : in out Heap.HeapRecord;
               Imports      : in     LexTokenManager.Seq_Algebra.Seq)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     Multiply_Token;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives SPARK_IO.File_Sys from *,
            --#                                Annotation.Start_String,
            --#                                Export_Width,
            --#                                Imports,
            --#                                LexTokenManager.State,
            --#                                Multiply_Token,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col,
            --#                                The_Heap &
            --#         The_Heap          from *,
            --#                                Imports,
            --#                                LexTokenManager.State,
            --#                                Multiply_Token;
            is
               Import       : LexTokenManager.Seq_Algebra.Member_Of_Seq;
               First_Import : Boolean;
               The_Iterator : SPARKProgram.Iteration.Iterator;
            begin
               Import       := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                         S        => Imports);
               First_Import := True;

               -- Imports might contain a "*", but it might not be the first
               -- member of the sequence.  SPARK _does_ require the "*" to appear
               -- first in the import list, so we scan for it alone on the first pass,
               -- write it out, then remove it from the sequence.
               -- Note that the sequence is disposed of after writing imports so it is
               -- OK to modify it here.
               loop
                  exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Import);
                  if LexTokenManager.Lex_String_Case_Insensitive_Compare
                    (Lex_Str1 => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                              M        => Import),
                     Lex_Str2 => Multiply_Token) =
                    LexTokenManager.Str_Eq then
                     Write_Import
                       (First_Import => First_Import,
                        Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        The_Heap     => The_Heap,
                        Import       => Import);
                     LexTokenManager.Seq_Algebra.Remove_Member (The_Heap    => The_Heap,
                                                                S           => Imports,
                                                                Given_Value => Multiply_Token);
                     exit;
                  end if;
                  Import := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                     M        => Import);
               end loop;

               -- If '*' was the only import in the seq then the seq is now empty so we don't
               -- need to write any more imports. Need to guard against this case as the
               -- Initialise routine has an implicit precondition that the sequence is not
               -- empty.
               if not LexTokenManager.Seq_Algebra.Is_Empty_Seq (The_Heap => The_Heap,
                                                                S        => Imports) then
                  SPARKProgram.Iteration.Initialise (The_Heap     => The_Heap,
                                                     The_Seq      => Imports,
                                                     The_Iterator => The_Iterator);
                  Write_Import
                    (First_Import => First_Import,
                     Output       => Output,
                     Start_Col    => Start_Col,
                     Export_Width => Export_Width,
                     The_Heap     => The_Heap,
                     Import       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));
                  loop
                     SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                                  The_Iterator => The_Iterator);
                     exit when SPARKProgram.Iteration.Complete (The_Iterator => The_Iterator);
                     Write_Import
                       (First_Import => First_Import,
                        Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        The_Heap     => The_Heap,
                        Import       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));
                  end loop;
               end if;
            end Write_Imports;

            procedure Substitute_Self_For_Multiply
              (The_Heap                      : in out Heap.HeapRecord;
               Exports                       : in     LexTokenManager.Seq_Algebra.Seq;
               Dependencies_With_Multiply    : in     LexTokenManager.Relation_Algebra.String.Relation;
               Dependencies_Without_Multiply : in     LexTokenManager.Relation_Algebra.String.Relation)
            --# global in     LexTokenManager.State;
            --#        in     Multiply_Token;
            --#        in out Statistics.TableUsage;
            --# derives Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Dependencies_Without_Multiply,
            --#                                    Dependencies_With_Multiply,
            --#                                    Exports,
            --#                                    LexTokenManager.State,
            --#                                    Multiply_Token,
            --#                                    The_Heap;
            is
               Imports                : LexTokenManager.Seq_Algebra.Seq;
               Export, Import         : LexTokenManager.Seq_Algebra.Member_Of_Seq;
               Export_Val, Import_Val : LexTokenManager.Lex_String;
            begin
               Export := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                   S        => Exports);
               loop
                  exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Export);
                  Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                             M        => Export);
                  LexTokenManager.Relation_Algebra.String.Row_Extraction
                    (The_Heap    => The_Heap,
                     R           => Dependencies_With_Multiply,
                     Given_Index => Export_Val,
                     S           => Imports);
                  Import := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                      S        => Imports);
                  loop
                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Import);
                     Import_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                M        => Import);
                     if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Import_Val,
                                                                             Lex_Str2 => Multiply_Token) =
                       LexTokenManager.Str_Eq then
                        Import_Val := Export_Val;
                     end if;
                     LexTokenManager.Relation_Algebra.String.Insert_Pair
                       (The_Heap => The_Heap,
                        R        => Dependencies_Without_Multiply,
                        I        => Export_Val,
                        J        => Import_Val);
                     Import := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                        M        => Import);
                  end loop;
                  LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                              S        => Imports);
                  Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                     M        => Export);
               end loop;
            end Substitute_Self_For_Multiply;

            procedure Write_Similar_Clauses
              (Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               Export_Width : in     E_Strings.Lengths;
               First_Export : in out Boolean;
               The_Heap     : in out Heap.HeapRecord;
               Exports      : in     LexTokenManager.Seq_Algebra.Seq;
               Dependencies : in     LexTokenManager.Relation_Algebra.String.Relation)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     Multiply_Token;
            --#        in     RW_Null_Token;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --#        in out Statistics.TableUsage;
            --# derives First_Export,
            --#         Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Dependencies,
            --#                                    Exports,
            --#                                    LexTokenManager.State,
            --#                                    Multiply_Token,
            --#                                    RW_Null_Token,
            --#                                    The_Heap &
            --#         SPARK_IO.File_Sys     from *,
            --#                                    Annotation.Start_String,
            --#                                    Dependencies,
            --#                                    Exports,
            --#                                    Export_Width,
            --#                                    First_Export,
            --#                                    LexTokenManager.State,
            --#                                    Multiply_Token,
            --#                                    Output,
            --#                                    RW_Null_Token,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    Start_Col,
            --#                                    The_Heap;
            is
               Compressed_Exports : LexTokenManager.Relation_Algebra.Relation;
               Compressed_Imports : LexTokenManager.Relation_Algebra.Relation;
               Compressed_Index   : Natural;

               procedure Find_Similar_Exports
                 (The_Heap        : in out Heap.HeapRecord;
                  Export          : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Dependencies    : in     LexTokenManager.Relation_Algebra.String.Relation;
                  Similar_Exports : in     LexTokenManager.Seq_Algebra.Seq;
                  Imports         : in     LexTokenManager.Seq_Algebra.Seq)
               --# global in     LexTokenManager.State;
               --#        in     RW_Null_Token;
               --#        in out Statistics.TableUsage;
               --# derives Statistics.TableUsage,
               --#         The_Heap              from *,
               --#                                    Dependencies,
               --#                                    Export,
               --#                                    Imports,
               --#                                    LexTokenManager.State,
               --#                                    RW_Null_Token,
               --#                                    Similar_Exports,
               --#                                    The_Heap;
               is
                  Other_Imports    : LexTokenManager.Seq_Algebra.Seq;
                  Other_Export     : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Other_Export_Val : LexTokenManager.Lex_String;

                  function Identical_Sequences
                    (The_Heap : Heap.HeapRecord;
                     S        : LexTokenManager.Seq_Algebra.Seq;
                     T        : LexTokenManager.Seq_Algebra.Seq)
                    return     Boolean
                  --# global in LexTokenManager.State;
                  is
                     M, N      : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                     Identical : Boolean;
                  begin
                     M         := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                            S        => S);
                     N         := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                            S        => T);
                     Identical := True;
                     loop
                        exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => M)
                          or else LexTokenManager.Seq_Algebra.Is_Null_Member (M => N);
                        if LexTokenManager.Lex_String_Case_Insensitive_Compare
                          (Lex_Str1 => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                    M        => M),
                           Lex_Str2 => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                    M        => N)) /=
                          LexTokenManager.Str_Eq then
                           Identical := False;
                           exit;
                        end if;
                        M := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                      M        => M);
                        N := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                      M        => N);
                     end loop;
                     return Identical
                       and then LexTokenManager.Seq_Algebra.Is_Null_Member (M => M)
                       and then LexTokenManager.Seq_Algebra.Is_Null_Member (M => N);
                  end Identical_Sequences;

               begin
                  Other_Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                           M        => Export);
                  loop
                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Other_Export);
                     Other_Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Other_Export);
                     if LexTokenManager.Lex_String_Case_Insensitive_Compare
                       (Lex_Str1 => Other_Export_Val,
                        Lex_Str2 => RW_Null_Token) /=
                       LexTokenManager.Str_Eq then
                        LexTokenManager.Relation_Algebra.String.Row_Extraction
                          (The_Heap    => The_Heap,
                           R           => Dependencies,
                           Given_Index => Other_Export_Val,
                           S           => Other_Imports);
                        if Identical_Sequences (The_Heap => The_Heap,
                                                S        => Imports,
                                                T        => Other_Imports) then
                           LexTokenManager.Seq_Algebra.Add_Member
                             (The_Heap    => The_Heap,
                              S           => Similar_Exports,
                              Given_Value => Other_Export_Val);
                        end if;
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Other_Imports);
                     end if;
                     Other_Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                              M        => Other_Export);
                  end loop;
               end Find_Similar_Exports;

               procedure Swap_Sequence (A, B : in out LexTokenManager.Seq_Algebra.Seq)
               --# derives A from B &
               --#         B from A;
               is
                  Temp : LexTokenManager.Seq_Algebra.Seq;
               begin
                  Temp := A;
                  A    := B;
                  B    := Temp;
               end Swap_Sequence;

               function Sequence_Length (The_Heap : Heap.HeapRecord;
                                         S        : LexTokenManager.Seq_Algebra.Seq) return Natural is
                  M      : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Length : Natural;
               begin
                  M      := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                      S        => S);
                  Length := 0;
                  loop
                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => M);
                     Length := Length + 1;
                     M      := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                        M        => M);
                  end loop;
                  return Length;
               end Sequence_Length;

               procedure Build_Compressed_Dependencies
                 (The_Heap           : in out Heap.HeapRecord;
                  Dependencies       : in     LexTokenManager.Relation_Algebra.String.Relation;
                  Exports            : in     LexTokenManager.Seq_Algebra.Seq;
                  Compressed_Exports :    out LexTokenManager.Relation_Algebra.Relation;
                  Compressed_Imports :    out LexTokenManager.Relation_Algebra.Relation;
                  Compressed_Index   :    out Natural)

               --# global in     LexTokenManager.State;
               --#        in     Multiply_Token;
               --#        in     RW_Null_Token;
               --#        in out Statistics.TableUsage;
               --# derives Compressed_Exports,
               --#         Compressed_Imports    from The_Heap &
               --#         Compressed_Index,
               --#         The_Heap              from Dependencies,
               --#                                    Exports,
               --#                                    LexTokenManager.State,
               --#                                    Multiply_Token,
               --#                                    RW_Null_Token,
               --#                                    The_Heap &
               --#         Statistics.TableUsage from *,
               --#                                    Dependencies,
               --#                                    Exports,
               --#                                    LexTokenManager.State,
               --#                                    Multiply_Token,
               --#                                    RW_Null_Token,
               --#                                    The_Heap;

               is
                  Export_Val      : LexTokenManager.Lex_String;
                  Export          : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Next_Export     : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Similar_Exports : LexTokenManager.Seq_Algebra.Seq;
                  Imports         : LexTokenManager.Seq_Algebra.Seq;

                  procedure Try_Adding_Self_Dependencies
                    (The_Heap        : in out Heap.HeapRecord;
                     Export          : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                     Dependencies    : in     LexTokenManager.Relation_Algebra.String.Relation;
                     Similar_Exports : in out LexTokenManager.Seq_Algebra.Seq;
                     Imports         : in out LexTokenManager.Seq_Algebra.Seq)
                  --# global in     LexTokenManager.State;
                  --#        in     Multiply_Token;
                  --#        in     RW_Null_Token;
                  --#        in out Statistics.TableUsage;
                  --# derives Imports,
                  --#         Similar_Exports,
                  --#         Statistics.TableUsage,
                  --#         The_Heap              from *,
                  --#                                    Dependencies,
                  --#                                    Export,
                  --#                                    Imports,
                  --#                                    LexTokenManager.State,
                  --#                                    Multiply_Token,
                  --#                                    RW_Null_Token,
                  --#                                    Similar_Exports,
                  --#                                    The_Heap;
                  is
                     Other_Export : LexTokenManager.Seq_Algebra.Member_Of_Seq;

                     procedure Try_Adding_Self_Dependency
                       (The_Heap        : in out Heap.HeapRecord;
                        Export          : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                        Other_Export    : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                        Dependencies    : in     LexTokenManager.Relation_Algebra.String.Relation;
                        Similar_Exports : in out LexTokenManager.Seq_Algebra.Seq;
                        Imports         : in out LexTokenManager.Seq_Algebra.Seq)
                     --# global in     LexTokenManager.State;
                     --#        in     RW_Null_Token;
                     --#        in out Statistics.TableUsage;
                     --# derives Imports,
                     --#         Similar_Exports,
                     --#         Statistics.TableUsage from *,
                     --#                                    Dependencies,
                     --#                                    Export,
                     --#                                    LexTokenManager.State,
                     --#                                    Other_Export,
                     --#                                    RW_Null_Token,
                     --#                                    Similar_Exports,
                     --#                                    The_Heap &
                     --#         The_Heap              from *,
                     --#                                    Dependencies,
                     --#                                    Export,
                     --#                                    Imports,
                     --#                                    LexTokenManager.State,
                     --#                                    Other_Export,
                     --#                                    RW_Null_Token,
                     --#                                    Similar_Exports;
                     is
                        Export_Val, Other_Export_Val : LexTokenManager.Lex_String;
                        Trial_Similar_Exports        : LexTokenManager.Seq_Algebra.Seq;
                        Trial_Imports                : LexTokenManager.Seq_Algebra.Seq;
                        TrialDependencies            : LexTokenManager.Relation_Algebra.String.Relation;
                     begin
                        Export_Val       := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                         M        => Export);
                        Other_Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                         M        => Other_Export);
                        LexTokenManager.Relation_Algebra.String.Create_Relation (The_Heap => The_Heap,
                                                                                 R        => TrialDependencies);
                        LexTokenManager.Relation_Algebra.String.Augment_Relation
                          (The_Heap => The_Heap,
                           A        => TrialDependencies,
                           B        => Dependencies);
                        LexTokenManager.Relation_Algebra.String.Insert_Pair
                          (The_Heap => The_Heap,
                           R        => TrialDependencies,
                           I        => Other_Export_Val,
                           J        => Other_Export_Val);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Trial_Similar_Exports);
                        LexTokenManager.Relation_Algebra.String.Row_Extraction
                          (The_Heap    => The_Heap,
                           R           => TrialDependencies,
                           Given_Index => Export_Val,
                           S           => Trial_Imports);
                        Find_Similar_Exports
                          (The_Heap        => The_Heap,
                           Export          => Export,
                           Dependencies    => TrialDependencies,
                           Similar_Exports => Trial_Similar_Exports,
                           Imports         => Trial_Imports);
                        if Sequence_Length (The_Heap => The_Heap,
                                            S        => Trial_Similar_Exports) >
                          Sequence_Length (The_Heap => The_Heap,
                                           S        => Similar_Exports) then
                           Swap_Sequence (A => Similar_Exports,
                                          B => Trial_Similar_Exports);
                           Swap_Sequence (A => Imports,
                                          B => Trial_Imports);
                           LexTokenManager.Relation_Algebra.String.Insert_Pair
                             (The_Heap => The_Heap,
                              R        => Dependencies,
                              I        => Other_Export_Val,
                              J        => Other_Export_Val);
                        end if;
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Trial_Similar_Exports);
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Trial_Imports);
                        LexTokenManager.Relation_Algebra.String.Dispose_Of_Relation (The_Heap => The_Heap,
                                                                                     R        => TrialDependencies);
                     end Try_Adding_Self_Dependency;

                  begin
                     if LexTokenManager.Seq_Algebra.Is_Member
                       (The_Heap    => The_Heap,
                        S           => Imports,
                        Given_Value => Multiply_Token) then
                        Try_Adding_Self_Dependency
                          (The_Heap        => The_Heap,
                           Export          => Export,
                           Other_Export    => Export,
                           Dependencies    => Dependencies,
                           Similar_Exports => Similar_Exports,
                           Imports         => Imports);
                        Other_Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                 M        => Export);
                        loop
                           exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Other_Export);
                           Try_Adding_Self_Dependency
                             (The_Heap        => The_Heap,
                              Export          => Export,
                              Other_Export    => Other_Export,
                              Dependencies    => Dependencies,
                              Similar_Exports => Similar_Exports,
                              Imports         => Imports);
                           Other_Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                    M        => Other_Export);
                        end loop;
                     end if;
                  end Try_Adding_Self_Dependencies;

                  procedure Try_Without_Multiply
                    (The_Heap        : in out Heap.HeapRecord;
                     Export          : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                     Exports         : in     LexTokenManager.Seq_Algebra.Seq;
                     Dependencies    : in     LexTokenManager.Relation_Algebra.String.Relation;
                     Similar_Exports : in out LexTokenManager.Seq_Algebra.Seq;
                     Imports         : in out LexTokenManager.Seq_Algebra.Seq)
                  --# global in     LexTokenManager.State;
                  --#        in     Multiply_Token;
                  --#        in     RW_Null_Token;
                  --#        in out Statistics.TableUsage;
                  --# derives Imports,
                  --#         Similar_Exports       from *,
                  --#                                    Dependencies,
                  --#                                    Export,
                  --#                                    Exports,
                  --#                                    LexTokenManager.State,
                  --#                                    Multiply_Token,
                  --#                                    RW_Null_Token,
                  --#                                    Similar_Exports,
                  --#                                    The_Heap &
                  --#         Statistics.TableUsage from *,
                  --#                                    Dependencies,
                  --#                                    Export,
                  --#                                    Exports,
                  --#                                    LexTokenManager.State,
                  --#                                    Multiply_Token,
                  --#                                    RW_Null_Token,
                  --#                                    The_Heap &
                  --#         The_Heap              from *,
                  --#                                    Dependencies,
                  --#                                    Export,
                  --#                                    Exports,
                  --#                                    Imports,
                  --#                                    LexTokenManager.State,
                  --#                                    Multiply_Token,
                  --#                                    RW_Null_Token,
                  --#                                    Similar_Exports;
                  is
                     Trial_Similar_Exports, Trial_Imports : LexTokenManager.Seq_Algebra.Seq;
                     Export_Val                           : LexTokenManager.Lex_String;
                     Dependencies_Without_Multiply        : LexTokenManager.Relation_Algebra.String.Relation;
                  begin
                     Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                M        => Export);
                     LexTokenManager.Relation_Algebra.String.Create_Relation
                       (The_Heap => The_Heap,
                        R        => Dependencies_Without_Multiply);
                     Substitute_Self_For_Multiply
                       (The_Heap                      => The_Heap,
                        Exports                       => Exports,
                        Dependencies_With_Multiply    => Dependencies,
                        Dependencies_Without_Multiply => Dependencies_Without_Multiply);
                     LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                             S        => Trial_Similar_Exports);
                     LexTokenManager.Relation_Algebra.String.Row_Extraction
                       (The_Heap    => The_Heap,
                        R           => Dependencies_Without_Multiply,
                        Given_Index => Export_Val,
                        S           => Trial_Imports);
                     Find_Similar_Exports
                       (The_Heap        => The_Heap,
                        Export          => Export,
                        Dependencies    => Dependencies_Without_Multiply,
                        Similar_Exports => Trial_Similar_Exports,
                        Imports         => Trial_Imports);
                     if Sequence_Length (The_Heap => The_Heap,
                                         S        => Trial_Similar_Exports) >
                       Sequence_Length (The_Heap => The_Heap,
                                        S        => Similar_Exports) then
                        Swap_Sequence (A => Similar_Exports,
                                       B => Trial_Similar_Exports);
                        Swap_Sequence (A => Imports,
                                       B => Trial_Imports);
                     end if;
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => Trial_Similar_Exports);
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => Trial_Imports);
                     LexTokenManager.Relation_Algebra.String.Dispose_Of_Relation
                       (The_Heap => The_Heap,
                        R        => Dependencies_Without_Multiply);
                  end Try_Without_Multiply;

                  procedure Remove_Members (The_Heap : in out Heap.HeapRecord;
                                            A, B     : in     LexTokenManager.Seq_Algebra.Seq)
                  --# global in LexTokenManager.State;
                  --# derives The_Heap from *,
                  --#                       A,
                  --#                       B,
                  --#                       LexTokenManager.State;
                  is
                     M, Next    : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                     Value_Of_M : LexTokenManager.Lex_String;
                  begin
                     M := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                    S        => A);
                     loop
                        exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => M);
                        Value_Of_M := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                   M        => M);
                        if LexTokenManager.Seq_Algebra.Is_Member (The_Heap    => The_Heap,
                                                                  S           => B,
                                                                  Given_Value => Value_Of_M) then
                           Next := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                            M        => M);
                           LexTokenManager.Seq_Algebra.Remove_Member (The_Heap    => The_Heap,
                                                                      S           => A,
                                                                      Given_Value => Value_Of_M);
                           M := Next;
                        else
                           M := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                         M        => M);
                        end if;
                     end loop;
                  end Remove_Members;

               begin
                  -- Create relations to store sequences of exports and their imports.
                  -- These two relations will be indexed by Compressed_Index, so for any given value
                  -- of Compressed_Index one relation gives the sequence of exports and the other
                  -- provides the sequence of imports from which they are derived.
                  LexTokenManager.Relation_Algebra.Create_Relation (The_Heap => The_Heap,
                                                                    R        => Compressed_Exports);
                  LexTokenManager.Relation_Algebra.Create_Relation (The_Heap => The_Heap,
                                                                    R        => Compressed_Imports);
                  Compressed_Index := Natural'First;
                  Export           := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                                S        => Exports);
                  -- Loop condition avoids potential RTE. Compressed_Index can never exceed bounds of
                  -- Natural in practice because it will never exceed the number of exports.
                  while Compressed_Index < Natural'Last loop
                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Export);
                     -- Look for other exports with the same dependency list, and store them
                     -- in the sequence Similar_Exports.
                     Export_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                M        => Export);
                     if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Export_Val,
                                                                             Lex_Str2 => RW_Null_Token) /=
                       LexTokenManager.Str_Eq then -- null derives comes last so ignore it here
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Similar_Exports);
                        LexTokenManager.Relation_Algebra.String.Row_Extraction
                          (The_Heap    => The_Heap,
                           R           => Dependencies,
                           Given_Index => Export_Val,
                           S           => Imports);
                        Find_Similar_Exports
                          (The_Heap        => The_Heap,
                           Export          => Export,
                           Dependencies    => Dependencies,
                           Similar_Exports => Similar_Exports,
                           Imports         => Imports);
                        Try_Adding_Self_Dependencies
                          (The_Heap        => The_Heap,
                           Export          => Export,
                           Dependencies    => Dependencies,
                           Similar_Exports => Similar_Exports,
                           Imports         => Imports);
                        Try_Without_Multiply
                          (The_Heap        => The_Heap,
                           Export          => Export,
                           Exports         => Exports,
                           Dependencies    => Dependencies,
                           Similar_Exports => Similar_Exports,
                           Imports         => Imports);
                        -- Rather than write the dependencies out directly here (in whatever order they
                        -- happen to be in) we build a new, compressed, dependency relation to be written
                        -- out (in a given order) once it is complete.
                        --
                        -- Note that if an export has no similar exports it *is* added to the compressed
                        -- sequence but it is *not* removed from the sequence of exports. (The implementations
                        -- of Find_Similar_Exports, Try_Adding_Self_Dependencies and Try_Without_Multiply depend on
                        -- this being the case.) Consequently, the sequence of exports should not be used
                        -- after calling this subprogram.
                        Compressed_Index := Compressed_Index + 1;
                        LexTokenManager.Relation_Algebra.Insert_Pair
                          (The_Heap => The_Heap,
                           R        => Compressed_Exports,
                           I        => Compressed_Index,
                           J        => Export_Val);
                        LexTokenManager.Relation_Algebra.Add_Row
                          (The_Heap => The_Heap,
                           R        => Compressed_Imports,
                           I        => Compressed_Index,
                           S        => Imports);

                        if LexTokenManager.Seq_Algebra.Is_Empty_Seq (The_Heap => The_Heap,
                                                                     S        => Similar_Exports) then
                           Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                              M        => Export);
                        else
                           LexTokenManager.Relation_Algebra.Add_Row
                             (The_Heap => The_Heap,
                              R        => Compressed_Exports,
                              I        => Compressed_Index,
                              S        => Similar_Exports);
                           Remove_Members (The_Heap => The_Heap,
                                           A        => Exports,
                                           B        => Similar_Exports);
                           Next_Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                   M        => Export);
                           LexTokenManager.Seq_Algebra.Remove_Member
                             (The_Heap    => The_Heap,
                              S           => Exports,
                              Given_Value => Export_Val);
                           Export := Next_Export;
                        end if;
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Similar_Exports);
                        LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                    S        => Imports);
                     else
                        -- if null token move on to next item
                        Export := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                           M        => Export);
                     end if;
                  end loop;
               end Build_Compressed_Dependencies;

               procedure Write_Dependencies_Alphabetic
                 (The_Heap           : in out Heap.HeapRecord;
                  Output             : in     SPARK_IO.File_Type;
                  Start_Col          : in     E_Strings.Positions;
                  Export_Width       : in     E_Strings.Lengths;
                  First_Export       : in out Boolean;
                  Compressed_Exports : in     LexTokenManager.Relation_Algebra.Relation;
                  Compressed_Imports : in     LexTokenManager.Relation_Algebra.Relation;
                  Compressed_Index   : in     Natural)

               --# global in     Annotation.Start_String;
               --#        in     LexTokenManager.State;
               --#        in     Multiply_Token;
               --#        in     SparkFormatCommandLineData.Content;
               --#        in out SPARK_IO.File_Sys;
               --#        in out Statistics.TableUsage;
               --# derives First_Export,
               --#         Statistics.TableUsage,
               --#         The_Heap              from *,
               --#                                    Compressed_Exports,
               --#                                    Compressed_Imports,
               --#                                    Compressed_Index,
               --#                                    LexTokenManager.State,
               --#                                    Multiply_Token,
               --#                                    The_Heap &
               --#         SPARK_IO.File_Sys     from *,
               --#                                    Annotation.Start_String,
               --#                                    Compressed_Exports,
               --#                                    Compressed_Imports,
               --#                                    Compressed_Index,
               --#                                    Export_Width,
               --#                                    First_Export,
               --#                                    LexTokenManager.State,
               --#                                    Multiply_Token,
               --#                                    Output,
               --#                                    SparkFormatCommandLineData.Content,
               --#                                    Start_Col,
               --#                                    The_Heap;
               is
                  Relations_Written  : SeqAlgebra.Seq;
                  Local_Index        : Natural;
                  Relation_Count     : Natural;
                  First_Alpha_Index  : Natural;
                  First_Alpha_Export : LexTokenManager.Lex_String;
                  Exports_To_Write   : LexTokenManager.Seq_Algebra.Seq;
                  Imports_To_Write   : LexTokenManager.Seq_Algebra.Seq;
                  The_Iterator       : SPARKProgram.Iteration.Iterator;
                  Current_String     : LexTokenManager.Lex_String;

                  procedure Write_Dependencies
                    (Output       : in     SPARK_IO.File_Type;
                     Start_Col    : in     E_Strings.Positions;
                     Export_Width : in     E_Strings.Lengths;
                     First_Export : in out Boolean;
                     The_Heap     : in out Heap.HeapRecord;
                     Exports      : in     LexTokenManager.Seq_Algebra.Seq;
                     Imports      : in     LexTokenManager.Seq_Algebra.Seq)
                  --# global in     Annotation.Start_String;
                  --#        in     LexTokenManager.State;
                  --#        in     Multiply_Token;
                  --#        in     SparkFormatCommandLineData.Content;
                  --#        in out SPARK_IO.File_Sys;
                  --# derives First_Export      from * &
                  --#         SPARK_IO.File_Sys from *,
                  --#                                Annotation.Start_String,
                  --#                                Exports,
                  --#                                Export_Width,
                  --#                                First_Export,
                  --#                                Imports,
                  --#                                LexTokenManager.State,
                  --#                                Multiply_Token,
                  --#                                Output,
                  --#                                SparkFormatCommandLineData.Content,
                  --#                                Start_Col,
                  --#                                The_Heap &
                  --#         The_Heap          from *,
                  --#                                Imports,
                  --#                                LexTokenManager.State,
                  --#                                Multiply_Token;
                  is
                     The_Iterator : SPARKProgram.Iteration.Iterator;

                     procedure Write_Similar_Export
                       (Output    : in SPARK_IO.File_Type;
                        Start_Col : in E_Strings.Positions;
                        The_Heap  : in Heap.HeapRecord;
                        Export    : in LexTokenManager.Seq_Algebra.Member_Of_Seq)
                     --# global in     Annotation.Start_String;
                     --#        in     LexTokenManager.State;
                     --#        in     SparkFormatCommandLineData.Content;
                     --#        in out SPARK_IO.File_Sys;
                     --# derives SPARK_IO.File_Sys from *,
                     --#                                Annotation.Start_String,
                     --#                                Export,
                     --#                                LexTokenManager.State,
                     --#                                Output,
                     --#                                SparkFormatCommandLineData.Content,
                     --#                                Start_Col,
                     --#                                The_Heap;
                     is
                     begin
                        SPARK_IO.Put_Line (Output, ",", 0);
                        Annotation.Write (Output    => Output,
                                          Start_Col => Start_Col);
                        SPARK_IO.Set_Col (Output, Export_Col (Start_Col => Start_Col));
                        E_Strings.Put_String
                          (File  => Output,
                           E_Str => LexTokenManager.Lex_String_To_String
                             (Lex_Str => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Export)));
                     end Write_Similar_Export;

                  begin
                     -- Dependency consists of <exports> from <imports>, so start with
                     -- the exports.
                     SPARKProgram.Iteration.Initialise (The_Heap     => The_Heap,
                                                        The_Seq      => Exports,
                                                        The_Iterator => The_Iterator);
                     Write_Export
                       (First_Export => First_Export,
                        Output       => Output,
                        Start_Col    => Start_Col,
                        The_Heap     => The_Heap,
                        Export       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));
                     SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                                  The_Iterator => The_Iterator);
                     -- if there are more exports derived from the same imports, write them out
                     while not SPARKProgram.Iteration.Complete (The_Iterator => The_Iterator) loop
                        Write_Similar_Export
                          (Output    => Output,
                           Start_Col => Start_Col,
                           The_Heap  => The_Heap,
                           Export    => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));
                        SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                                     The_Iterator => The_Iterator);
                     end loop;
                     -- from
                     Write_From (Output       => Output,
                                 Start_Col    => Start_Col,
                                 Export_Width => Export_Width);
                     -- the imports
                     Write_Imports
                       (Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        The_Heap     => The_Heap,
                        Imports      => Imports);
                  end Write_Dependencies;

               begin
                  -- Need to find the alphabetical first member out of all the export sequences in
                  -- the Exports_To_Write relation. The corresponding dependency can then be written
                  -- out, after which it can be disposed of. Repeat until all relations have been
                  -- written.
                  SeqAlgebra.CreateSeq (TheHeap => The_Heap,
                                        S       => Relations_Written);
                  Relation_Count := Compressed_Index; -- Keep a record of the total number of relations
                  loop -- until all exports have been written
                     First_Alpha_Index  := Natural'First;
                     Local_Index        := Relation_Count;
                     First_Alpha_Export := LexTokenManager.Null_String;
                     -- Go through all the export sequences (skipping those we have already written) looking
                     -- for the first export in alphabetical order.
                     while Local_Index > Natural'First loop
                        if not SeqAlgebra.IsMember (TheHeap    => The_Heap,
                                                    S          => Relations_Written,
                                                    GivenValue => Local_Index) then
                           LexTokenManager.Relation_Algebra.Row_Extraction
                             (The_Heap    => The_Heap,
                              R           => Compressed_Exports,
                              Given_Index => Local_Index,
                              S           => Exports_To_Write);
                           -- Find the first member of the current export sequence.
                           -- In this case we use initialise to find us the first member but we never go on to iterate
                           -- over the list.
                           SPARKProgram.Iteration.Initialise
                             (The_Heap     => The_Heap,
                              The_Seq      => Exports_To_Write,
                              The_Iterator => The_Iterator);
                           -- If this is the first iteration then the item just returned must be the best match so far.
                           -- Otherwise, if it is better than our current best match then this export sequence becomes the one to
                           --write
                           Current_String := SPARKProgram.Iteration.Current_String (The_Iterator => The_Iterator);
                           if First_Alpha_Index = Natural'First
                             or else -- always do it on first iteration
                             LexTokenManager.Lex_String_Case_Insensitive_Compare
                             (Lex_Str1 => Current_String,
                              Lex_Str2 => First_Alpha_Export) =
                             LexTokenManager.Str_First then
                              First_Alpha_Export := Current_String;
                              First_Alpha_Index  := Local_Index;
                           end if;
                        end if;
                        Local_Index := Local_Index - 1;
                     end loop;
                     if First_Alpha_Index = Natural'First then -- defensive - should always be false
                        exit;
                     end if;
                     -- First_Alpha_Index gives us the relation index for the next dependency to be written
                     -- Write it out, then add it to the sequence of relations that have been written.
                     LexTokenManager.Relation_Algebra.Row_Extraction
                       (The_Heap    => The_Heap,
                        R           => Compressed_Exports,
                        Given_Index => First_Alpha_Index,
                        S           => Exports_To_Write);
                     LexTokenManager.Relation_Algebra.Row_Extraction
                       (The_Heap    => The_Heap,
                        R           => Compressed_Imports,
                        Given_Index => First_Alpha_Index,
                        S           => Imports_To_Write);
                     Write_Dependencies
                       (Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        First_Export => First_Export,
                        The_Heap     => The_Heap,
                        Exports      => Exports_To_Write,
                        Imports      => Imports_To_Write);
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => Exports_To_Write);
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => Imports_To_Write);
                     SeqAlgebra.AddMember (TheHeap    => The_Heap,
                                           S          => Relations_Written,
                                           GivenValue => First_Alpha_Index);
                     -- Exit if all relations have now been added to Relations_Written
                     exit when SeqAlgebra.Length (The_Heap, Relations_Written) >= Relation_Count;
                  end loop; -- until all relations written
                  SeqAlgebra.DisposeOfSeq (The_Heap, Relations_Written);
               end Write_Dependencies_Alphabetic;

            begin
               -- Write_Similar_Clauses
               -- Compress the dependencies if possible. Store the results in Compressed_Exports
               -- and Compressed_Imports, indexed by Compressed_Index.
               Build_Compressed_Dependencies
                 (The_Heap           => The_Heap,
                  Dependencies       => Dependencies,
                  Exports            => Exports,
                  Compressed_Exports => Compressed_Exports,
                  Compressed_Imports => Compressed_Imports,
                  Compressed_Index   => Compressed_Index);
               -- Extract the compressed dependencies and write them out.
               Write_Dependencies_Alphabetic
                 (The_Heap           => The_Heap,
                  Output             => Output,
                  Start_Col          => Start_Col,
                  Export_Width       => Export_Width,
                  First_Export       => First_Export,
                  Compressed_Exports => Compressed_Exports,
                  Compressed_Imports => Compressed_Imports,
                  Compressed_Index   => Compressed_Index);
            end Write_Similar_Clauses;

            procedure Write_Clauses
              (Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               Export_Width : in     E_Strings.Lengths;
               First_Export : in out Boolean;
               The_Heap     : in out Heap.HeapRecord;
               Exports      : in     LexTokenManager.Seq_Algebra.Seq;
               Dependencies : in     LexTokenManager.Relation_Algebra.String.Relation)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     Multiply_Token;
            --#        in     RW_Null_Token;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --#        in out Statistics.TableUsage;
            --# derives First_Export,
            --#         Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Dependencies,
            --#                                    Exports,
            --#                                    LexTokenManager.State,
            --#                                    Multiply_Token,
            --#                                    RW_Null_Token,
            --#                                    The_Heap &
            --#         SPARK_IO.File_Sys     from *,
            --#                                    Annotation.Start_String,
            --#                                    Dependencies,
            --#                                    Exports,
            --#                                    Export_Width,
            --#                                    First_Export,
            --#                                    LexTokenManager.State,
            --#                                    Multiply_Token,
            --#                                    Output,
            --#                                    RW_Null_Token,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    Start_Col,
            --#                                    The_Heap;
            is
               Imports                       : LexTokenManager.Seq_Algebra.Seq;
               Export_Val                    : LexTokenManager.Lex_String;
               Dependencies_Without_Multiply : LexTokenManager.Relation_Algebra.String.Relation;
               The_Iterator                  : SPARKProgram.Iteration.Iterator;
            begin

               -- This writes out the clauses in uncompressed form, ie no lists of exports sharing the
               -- same list of imports, and no '*'.

               LexTokenManager.Relation_Algebra.String.Create_Relation (The_Heap => The_Heap,
                                                                        R        => Dependencies_Without_Multiply);
               Substitute_Self_For_Multiply
                 (The_Heap                      => The_Heap,
                  Exports                       => Exports,
                  Dependencies_With_Multiply    => Dependencies,
                  Dependencies_Without_Multiply => Dependencies_Without_Multiply);

               SPARKProgram.Iteration.Initialise (The_Heap     => The_Heap,
                                                  The_Seq      => Exports,
                                                  The_Iterator => The_Iterator);

               while not SPARKProgram.Iteration.Complete (The_Iterator => The_Iterator) loop

                  Export_Val :=
                    LexTokenManager.Seq_Algebra.Value_Of_Member
                    (The_Heap => The_Heap,
                     M        => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));

                  -- Null dependency clause must come last so don't write it here
                  if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Export_Val,
                                                                          Lex_Str2 => RW_Null_Token) /=
                    LexTokenManager.Str_Eq then

                     -- export
                     Write_Export
                       (First_Export => First_Export,
                        Output       => Output,
                        Start_Col    => Start_Col,
                        The_Heap     => The_Heap,
                        Export       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));

                     Write_From (Output       => Output,
                                 Start_Col    => Start_Col,
                                 Export_Width => Export_Width); --from

                     -- imports
                     LexTokenManager.Relation_Algebra.String.Row_Extraction
                       (The_Heap    => The_Heap,
                        R           => Dependencies_Without_Multiply,
                        Given_Index => Export_Val,
                        S           => Imports);
                     Write_Imports
                       (Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        The_Heap     => The_Heap,
                        Imports      => Imports);
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => Imports);
                  end if;

                  SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                               The_Iterator => The_Iterator);

               end loop;

               LexTokenManager.Relation_Algebra.String.Dispose_Of_Relation
                 (The_Heap => The_Heap,
                  R        => Dependencies_Without_Multiply);

            end Write_Clauses;

            procedure Write_Null_Import_List
              (Output       : in     SPARK_IO.File_Type;
               Start_Col    : in     E_Strings.Positions;
               Export_Width : in     E_Strings.Lengths;
               First_Export : in     Boolean;
               The_Heap     : in out Heap.HeapRecord;
               Dependencies : in     LexTokenManager.Relation_Algebra.String.Relation)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     RW_Null_Token;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --#        in out Statistics.TableUsage;
            --# derives SPARK_IO.File_Sys     from *,
            --#                                    Annotation.Start_String,
            --#                                    Dependencies,
            --#                                    Export_Width,
            --#                                    First_Export,
            --#                                    LexTokenManager.State,
            --#                                    Output,
            --#                                    RW_Null_Token,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    Start_Col,
            --#                                    The_Heap &
            --#         Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Dependencies,
            --#                                    LexTokenManager.State,
            --#                                    RW_Null_Token,
            --#                                    The_Heap;
            is
               Imports      : LexTokenManager.Seq_Algebra.Seq;
               Import       : LexTokenManager.Seq_Algebra.Member_Of_Seq;
               First_Import : Boolean;
               The_Iterator : SPARKProgram.Iteration.Iterator;

               procedure Write_Null
                 (First_Export : in Boolean;
                  Output       : in SPARK_IO.File_Type;
                  Start_Col    : in E_Strings.Positions)
               --# global in     Annotation.Start_String;
               --#        in     SparkFormatCommandLineData.Content;
               --#        in out SPARK_IO.File_Sys;
               --# derives SPARK_IO.File_Sys from *,
               --#                                Annotation.Start_String,
               --#                                First_Export,
               --#                                Output,
               --#                                SparkFormatCommandLineData.Content,
               --#                                Start_Col;
               is
               begin
                  if not First_Export then
                     SPARK_IO.Put_Line (Output, " &", 0);
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                  elsif SparkFormatCommandLineData.Content.Export_Indent /= SparkFormatCommandLineData.Inline then
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                  end if;

                  SPARK_IO.Set_Col (Output, Export_Col (Start_Col => Start_Col));
                  SPARK_IO.Put_String (Output, "null", 0);
               end Write_Null;

            begin

               LexTokenManager.Relation_Algebra.String.Row_Extraction
                 (The_Heap    => The_Heap,
                  R           => Dependencies,
                  Given_Index => RW_Null_Token,
                  S           => Imports);

               -- This procedure can be called even if there is no null import list. If the
               -- sequence is null then don't write it out.
               Import := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                   S        => Imports);

               if not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Import) then

                  SPARKProgram.Iteration.Initialise (The_Heap     => The_Heap,
                                                     The_Seq      => Imports,
                                                     The_Iterator => The_Iterator);

                  Write_Null (First_Export => First_Export,
                              Output       => Output,
                              Start_Col    => Start_Col); -- null
                  Write_From (Output       => Output,
                              Start_Col    => Start_Col,
                              Export_Width => Export_Width); -- from

                  -- Now write out the list of imports in the requested order
                  First_Import := True;

                  Write_Import
                    (First_Import => First_Import,
                     Output       => Output,
                     Start_Col    => Start_Col,
                     Export_Width => Export_Width,
                     The_Heap     => The_Heap,
                     Import       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));

                  SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                               The_Iterator => The_Iterator);

                  while not SPARKProgram.Iteration.Complete (The_Iterator => The_Iterator) loop

                     Write_Import
                       (First_Import => First_Import,
                        Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        The_Heap     => The_Heap,
                        Import       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator));

                     SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                                  The_Iterator => The_Iterator);

                  end loop;

               end if;

               LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                           S        => Imports);

            end Write_Null_Import_List;

         begin

            if OK then

               Annotation.Write (Output    => Output,
                                 Start_Col => Start_Col);
               Write_Derives (Output    => Output,
                              Start_Col => Start_Col);
               First_Export := True;
               Export_Width := Longest_Export (The_Heap => The_Heap,
                                               Exports  => Exports);

               case SparkFormatCommandLineData.Content.Operation is

                  when SparkFormatCommandLineData.Compress =>

                     Write_Similar_Clauses
                       (Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        First_Export => First_Export,
                        The_Heap     => The_Heap,
                        Exports      => Exports,
                        Dependencies => Dependencies);

                  when SparkFormatCommandLineData.Expand =>

                     Write_Clauses
                       (Output       => Output,
                        Start_Col    => Start_Col,
                        Export_Width => Export_Width,
                        First_Export => First_Export,
                        The_Heap     => The_Heap,
                        Exports      => Exports,
                        Dependencies => Dependencies);

               end case;

               Write_Null_Import_List
                 (Output       => Output,
                  Start_Col    => Start_Col,
                  Export_Width => Export_Width,
                  First_Export => First_Export,
                  The_Heap     => The_Heap,
                  Dependencies => Dependencies);

               SPARK_IO.Put_Line (Output, ";", 0);

            else
               File_IO.Reset (Temporary_File => Temporary_File);
               SPARKProgram.Copy (Input  => Temporary_File,
                                  Output => Output);

            end if;

            LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                        S        => Exports);
            LexTokenManager.Relation_Algebra.String.Dispose_Of_Relation (The_Heap => The_Heap,
                                                                         R        => Dependencies);
            File_IO.Delete (Temporary_File => Temporary_File);

         end Reformat;

      end Derives_List;

      package body Declare_List is

         Keyword : constant String := "declare";

         -- checks it's at the start of a line up to "--# declare"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

         -- checks for ";" at end of line
         function Is_End (Input_Line : E_Strings.T) return Boolean is
            Result : Boolean;
         begin

            Result := False;

            for I in E_Strings.Lengths range E_Strings.Positions'First .. E_Strings.Get_Length (E_Str => Input_Line) loop
               if E_Strings.Get_Element (E_Str => Input_Line,
                                         Pos   => I) = ';' then
                  Result := True;
                  exit;
               end if;
            end loop;

            return Result;

         end Is_End;

      end Declare_List;

      package body Proof_List is

         Keyword_Pre    : constant String := "pre";
         Keyword_Post   : constant String := "post";
         Keyword_Return : constant String := "return";

         -- checks it's at the start of a line up to "--# pre" or "--# post" or "--# return"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword_Pre) or
              SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                     Match_Keyword => Keyword_Post) or
              SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                     Match_Keyword => Keyword_Return);
         end Is_Start;

         -- The 'Is_End' for proof annotations below is not called anywhere, and thus has
         -- not been tested.

         -- checks for ";" at end of line
         function Is_End (Input_Line : E_Strings.T) return Boolean is
            Result : Boolean;
         begin

            Result := False;

            for I in E_Strings.Lengths range E_Strings.Positions'First .. E_Strings.Get_Length (E_Str => Input_Line) loop
               if E_Strings.Get_Element (E_Str => Input_Line,
                                         Pos   => I) = ';' then
                  Result := True;
                  exit;
               end if;
            end loop;

            return Result;

         end Is_End;

      end Proof_List;

      package body Globals_List is

         Keyword : constant String := "global";

         Consecutive_Empty_Lines : Natural := 0;

         -- checks it's at the start of a line up to "--# global"
         function Is_Start (Input_Line : E_Strings.T) return Boolean is
         begin
            return SPARK_Keyword_Matching.Match_At_Start (Input_Line    => Input_Line,
                                                          Match_Keyword => Keyword);
         end Is_Start;

         --Here the end of a list of global declarations is detected.
         --Unfortunately, the SPARK syntax for globals does not have a unique terminator.
         --The ';' is used as a separator between different modes or as a terminator. Thus,
         --The end of a list of globals is detected by the end of a SPARK comment block, or
         --the start of a new comment item. Every possible following SPARK annotation item
         --needs to be considered, otherwise the real end of a global declaration may not be
         --detected. See SEPR: 2674
         function Is_End (Input_Line : E_Strings.T) return Boolean is
            Result              : Boolean;
            Is_Annotation_Start : Boolean;
            Index               : E_Strings.Lengths;
         begin

            if Derives_List.Is_Start (Input_Line => Input_Line) or
              Declare_List.Is_Start (Input_Line => Input_Line) or
              Proof_List.Is_Start (Input_Line => Input_Line) or
              Accept_List.Is_Start (Input_Line => Input_Line) or
              End_List.Is_Start (Input_Line => Input_Line) or
              For_List.Is_Start (Input_Line => Input_Line) or
              Function_List.Is_Start (Input_Line => Input_Line) or
              Type_List.Is_Start (Input_Line => Input_Line) or
              Assert_List.Is_Start (Input_Line => Input_Line) then
               Result := True;
            else
               Index := 1;
               --# accept Flow_Message, 10, Index, "Final value of Index is not required";
               Annotation.Is_Start (Input_Line => Input_Line,
                                    Index      => Index,
                                    OK         => Is_Annotation_Start);
               --# end accept;
               Result := not (Is_Annotation_Start or E_Strings.Is_Empty (E_Str => E_Strings.Trim (Input_Line)));
            end if;

            return Result;

         end Is_End;

         procedure Increment_Consecutive_Empty_Lines is
         begin
            Consecutive_Empty_Lines := Consecutive_Empty_Lines + 1;
         end Increment_Consecutive_Empty_Lines;

         procedure Reset_Consecutive_Empty_Lines is
         begin
            Consecutive_Empty_Lines := 0;
         end Reset_Consecutive_Empty_Lines;

         function No_Empty_Lines return Boolean is
         begin
            return Consecutive_Empty_Lines = 0;
         end No_Empty_Lines;

         procedure Parse
           (Temporary_File   : in out SPARK_IO.File_Type;
            Start_Col        :    out E_Strings.Positions;
            The_Heap         : in out Heap.HeapRecord;
            Global_Variables :    out Global_Variables_Type;
            OK               :    out Boolean)
         is

            Token   : SP_Symbols.SP_Terminal;
            Lex_Val : LexTokenManager.Lex_Value;

            procedure Create (The_Heap         : in out Heap.HeapRecord;
                              Global_Variables :    out Global_Variables_Type)
            --# global in out Statistics.TableUsage;
            --# derives Global_Variables,
            --#         The_Heap              from The_Heap &
            --#         Statistics.TableUsage from *,
            --#                                    The_Heap;
            is
               Unmoded_Global_Variables, In_Global_Variables, In_Out_Global_Variables, Out_Global_Variables :
                 LexTokenManager.Seq_Algebra.Seq;
            begin
               LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                       S        => Unmoded_Global_Variables);
               LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                       S        => In_Global_Variables);
               LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                       S        => In_Out_Global_Variables);
               LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                       S        => Out_Global_Variables);
               Global_Variables :=
                 Global_Variables_Type'
                 (Unmoded     => Unmoded_Global_Variables,
                  In_Mode     => In_Global_Variables,
                  In_Out_Mode => In_Out_Global_Variables,
                  Out_Mode    => Out_Global_Variables);
            end Create;

            procedure Parse_Global_Variable_Clauses
              (Temporary_File   : in     SPARK_IO.File_Type;
               Token            : in     SP_Symbols.SP_Terminal;
               Lex_Val          : in     LexTokenManager.Lex_Value;
               The_Heap         : in out Heap.HeapRecord;
               Global_Variables : in     Global_Variables_Type;
               OK               :    out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in out ErrorHandler.Error_Context;
            --#        in out LexTokenManager.State;
            --#        in out SparkLex.Curr_Line;
            --#        in out SPARK_IO.File_Sys;
            --#        in out Statistics.TableUsage;
            --# derives ErrorHandler.Error_Context,
            --#         LexTokenManager.State,
            --#         OK,
            --#         SparkLex.Curr_Line,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         LexTokenManager.State,
            --#                                         Lex_Val,
            --#                                         SparkLex.Curr_Line,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Temporary_File,
            --#                                         Token &
            --#         Statistics.TableUsage,
            --#         The_Heap                   from *,
            --#                                         CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Global_Variables,
            --#                                         LexTokenManager.State,
            --#                                         Lex_Val,
            --#                                         SparkLex.Curr_Line,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Temporary_File,
            --#                                         The_Heap,
            --#                                         Token;
            is

               Next_Token   : SP_Symbols.SP_Terminal;
               Next_Lex_Val : LexTokenManager.Lex_Value;

               procedure Parse_Global_Variable_List
                 (Temporary_File   : in     SPARK_IO.File_Type;
                  Token            : in out SP_Symbols.SP_Terminal;
                  Lex_Val          : in out LexTokenManager.Lex_Value;
                  The_Heap         : in out Heap.HeapRecord;
                  Global_Variables : in     Global_Variables_Type;
                  OK               :    out Boolean)
               --# global in     CommandLineData.Content;
               --#        in     Dictionary.Dict;
               --#        in out ErrorHandler.Error_Context;
               --#        in out LexTokenManager.State;
               --#        in out SparkLex.Curr_Line;
               --#        in out SPARK_IO.File_Sys;
               --#        in out Statistics.TableUsage;
               --# derives ErrorHandler.Error_Context,
               --#         LexTokenManager.State,
               --#         Lex_Val,
               --#         OK,
               --#         SparkLex.Curr_Line,
               --#         SPARK_IO.File_Sys,
               --#         Token                      from CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         Token &
               --#         Statistics.TableUsage,
               --#         The_Heap                   from *,
               --#                                         CommandLineData.Content,
               --#                                         Dictionary.Dict,
               --#                                         ErrorHandler.Error_Context,
               --#                                         Global_Variables,
               --#                                         LexTokenManager.State,
               --#                                         Lex_Val,
               --#                                         SparkLex.Curr_Line,
               --#                                         SPARK_IO.File_Sys,
               --#                                         Temporary_File,
               --#                                         The_Heap,
               --#                                         Token;
               is
                  Mode               : Modes;
                  Dotted_Simple_Name : E_Strings.T;
                  Global_Variable    : LexTokenManager.Lex_String;
               begin

                  OK   := True;
                  Mode := Unmoded;

                  case Token is
                     when SP_Symbols.RWin =>
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Lex_Val);
                        case Token is
                           when SP_Symbols.RWout =>
                              Mode := In_Out_Mode;
                              File_IO.Lex (Temporary_File => Temporary_File,
                                           Token          => Token,
                                           Lex_Val        => Lex_Val);
                           when SP_Symbols.identifier =>
                              Mode := In_Mode;
                           when others =>
                              OK := False;
                        end case;
                     when SP_Symbols.RWout =>
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Lex_Val);
                        Mode := Out_Mode;
                     when SP_Symbols.identifier =>
                        Mode := Unmoded;
                     when others =>
                        OK := False;
                  end case;

                  loop
                     exit when not OK;
                     case Token is
                        when SP_Symbols.identifier =>
                           Dotted_Simple_Name := LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str);
                           File_IO.Lex (Temporary_File => Temporary_File,
                                        Token          => Token,
                                        Lex_Val        => Lex_Val);
                           loop
                              exit when Token /= SP_Symbols.point;
                              E_Strings.Append_String (E_Str => Dotted_Simple_Name,
                                                       Str   => ".");
                              File_IO.Lex (Temporary_File => Temporary_File,
                                           Token          => Token,
                                           Lex_Val        => Lex_Val);
                              if Token = SP_Symbols.identifier then
                                 E_Strings.Append_Examiner_String
                                   (E_Str1 => Dotted_Simple_Name,
                                    E_Str2 => LexTokenManager.Lex_String_To_String (Lex_Str => Lex_Val.Token_Str));
                                 File_IO.Lex (Temporary_File => Temporary_File,
                                              Token          => Token,
                                              Lex_Val        => Lex_Val);
                              else
                                 OK := False;
                              end if;
                              exit when not OK;
                           end loop;
                           if OK then
                              LexTokenManager.Insert_Examiner_String (Str     => Dotted_Simple_Name,
                                                                      Lex_Str => Global_Variable);
                              LexTokenManager.Seq_Algebra.Add_Member
                                (The_Heap    => The_Heap,
                                 S           => Global_Variables (Mode),
                                 Given_Value => Global_Variable);
                           end if;
                        when SP_Symbols.comma =>
                           null;
                        when others =>
                           OK := False;
                     end case;
                     exit when not OK or Token = SP_Symbols.semicolon;
                     if Token = SP_Symbols.comma then
                        File_IO.Lex (Temporary_File => Temporary_File,
                                     Token          => Token,
                                     Lex_Val        => Lex_Val);
                     else
                        OK := False;
                     end if;
                  end loop;

               end Parse_Global_Variable_List;

            begin

               OK           := True;
               Next_Token   := Token;
               Next_Lex_Val := Lex_Val;

               loop
                  exit when Next_Token = SP_Symbols.annotation_end;
                  Parse_Global_Variable_List
                    (Temporary_File   => Temporary_File,
                     Token            => Next_Token,
                     Lex_Val          => Next_Lex_Val,
                     The_Heap         => The_Heap,
                     Global_Variables => Global_Variables,
                     OK               => OK);
                  if OK then
                     File_IO.Lex (Temporary_File => Temporary_File,
                                  Token          => Next_Token,
                                  Lex_Val        => Next_Lex_Val);
                     case Next_Token is
                        when SP_Symbols.annotation_end | SP_Symbols.RWin | SP_Symbols.RWout | SP_Symbols.identifier =>
                           null;
                        when others =>
                           OK := False;
                     end case;
                  end if;
                  exit when not OK;
               end loop;

            end Parse_Global_Variable_Clauses;

         begin

            File_IO.Reset (Temporary_File => Temporary_File);
            SparkLex.Clear_Line_Context;
            Create (The_Heap         => The_Heap,
                    Global_Variables => Global_Variables);
            File_IO.Lex (Temporary_File => Temporary_File,
                         Token          => Token,
                         Lex_Val        => Lex_Val);

            if Token = SP_Symbols.annotation_start then
               Start_Col := Lex_Val.Position.Start_Pos;
               -- we know Start_Col can't be zero because the line can't be empty
               --# accept Flow_Message, 10, Lex_Val, "The next symbol should be 'global', so we don't need the Lex_Val";
               File_IO.Lex (Temporary_File => Temporary_File,
                            Token          => Token,
                            Lex_Val        => Lex_Val);
               --# end accept;
               if Token = SP_Symbols.RWglobal then
                  File_IO.Lex (Temporary_File => Temporary_File,
                               Token          => Token,
                               Lex_Val        => Lex_Val);
                  Parse_Global_Variable_Clauses
                    (Temporary_File   => Temporary_File,
                     Token            => Token,
                     Lex_Val          => Lex_Val,
                     The_Heap         => The_Heap,
                     Global_Variables => Global_Variables,
                     OK               => OK);
               else
                  OK := False;
               end if;
            else
               OK := False;
            end if;
            --# accept Flow_Message, 602, Start_Col, Start_Col, "Start_Col may not be set if not OK";
         end Parse;

         procedure Reformat
           (OK                    : in     Boolean;
            Temporary_File        : in out SPARK_IO.File_Type;
            Output                : in     SPARK_IO.File_Type;
            Start_Col             : in     E_Strings.Positions;
            The_Heap              : in out Heap.HeapRecord;
            Function_Or_Procedure : in     Subprogram.Subprogram_Type;
            Global_Variables      : in     Global_Variables_Type;
            Imports               : in     LexTokenManager.Seq_Algebra.Seq;
            Exports               : in     LexTokenManager.Seq_Algebra.Seq)
         is

            Revised_Global_Variables : Global_Variables_Type;
            First_Global_Variable    : Boolean;
            An_Export_Is_Excluded    : Boolean;

            function Global_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions is
            begin
               return Start_Col + 4; -- length of "--# "
            end Global_Col;

            procedure Write_Global (Output    : in SPARK_IO.File_Type;
                                    Start_Col : in E_Strings.Positions)
            --# global in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives SPARK_IO.File_Sys from *,
            --#                                Output,
            --#                                SparkFormatCommandLineData.Content,
            --#                                Start_Col;
            is
            begin
               SPARK_IO.Set_Col (Output, Global_Col (Start_Col => Start_Col));
               SPARK_IO.Put_String (Output, "global", 0);
               -- If GlobalIndent is not Inline, then don't put out a trailing space,
               -- since this will be rejected by GNAT -gnatyb style check mode.
               if SparkFormatCommandLineData.Content.Global_Indent = SparkFormatCommandLineData.Inline then
                  SPARK_IO.Put_String (Output, " ", 0);
               end if;
            end Write_Global;

            procedure Remove_Excluded_Export
              (The_Heap         : in out Heap.HeapRecord;
               Imports          : in     LexTokenManager.Seq_Algebra.Seq;
               Exports          : in     LexTokenManager.Seq_Algebra.Seq;
               Global_Variables : in     Global_Variables_Type)
            --# global in     LexTokenManager.State;
            --#        in out Statistics.TableUsage;
            --# derives Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Exports,
            --#                                    Global_Variables,
            --#                                    Imports,
            --#                                    LexTokenManager.State,
            --#                                    The_Heap;
            is
               Global_Variable     : LexTokenManager.Seq_Algebra.Member_Of_Seq;
               Global_Variable_Val : LexTokenManager.Lex_String;
            begin
               --  Iterate through all global variable modes to remove
               --  excluded export and all imported variables exclusively
               --  related to the excluded exported variable.

               --  An out mode global which is no longer exported should be removed
               Global_Variable :=
                 LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                           S        => Global_Variables (Out_Mode));

               while not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable) loop
                  Global_Variable_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Global_Variable);
                  Global_Variable     := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                  M        => Global_Variable);

                  if not LexTokenManager.Seq_Algebra.Is_Member
                    (The_Heap    => The_Heap,
                     S           => Exports,
                     Given_Value => Global_Variable_Val) then
                     LexTokenManager.Seq_Algebra.Remove_Member
                       (The_Heap    => The_Heap,
                        S           => Global_Variables (Out_Mode),
                        Given_Value => Global_Variable_Val);
                  end if;
               end loop;

               --  An in out mode global which is no longer exported should
               --  be removed from the in out mode globals and if it is still
               --  and imported variable it should be added to the in mode globals
               Global_Variable :=
                 LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                           S        => Global_Variables (In_Out_Mode));

               while not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable) loop
                  Global_Variable_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Global_Variable);
                  Global_Variable     := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                  M        => Global_Variable);

                  if not LexTokenManager.Seq_Algebra.Is_Member
                    (The_Heap    => The_Heap,
                     S           => Exports,
                     Given_Value => Global_Variable_Val) then
                     LexTokenManager.Seq_Algebra.Remove_Member
                       (The_Heap    => The_Heap,
                        S           => Global_Variables (In_Out_Mode),
                        Given_Value => Global_Variable_Val);
                     if LexTokenManager.Seq_Algebra.Is_Member
                       (The_Heap    => The_Heap,
                        S           => Imports,
                        Given_Value => Global_Variable_Val) then
                        LexTokenManager.Seq_Algebra.Add_Member
                          (The_Heap    => The_Heap,
                           S           => Global_Variables (In_Mode),
                           Given_Value => Global_Variable_Val);
                     end if;
                  end if;
               end loop;

               --  An in mode global which is no longer imported should
               --  be removed from the in mode globals.
               Global_Variable :=
                 LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                           S        => Global_Variables (In_Mode));

               while not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable) loop
                  Global_Variable_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Global_Variable);
                  Global_Variable     := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                  M        => Global_Variable);

                  if not LexTokenManager.Seq_Algebra.Is_Member
                    (The_Heap    => The_Heap,
                     S           => Imports,
                     Given_Value => Global_Variable_Val) then
                     LexTokenManager.Seq_Algebra.Remove_Member
                       (The_Heap    => The_Heap,
                        S           => Global_Variables (In_Mode),
                        Given_Value => Global_Variable_Val);
                  end if;
               end loop;

               --  An unmoded global which is no longer exported or imported should
               --  be removed from the unmoded globals.
               Global_Variable :=
                 LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                           S        => Global_Variables (Unmoded));

               while not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable) loop
                  Global_Variable_Val := LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                      M        => Global_Variable);
                  Global_Variable     := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                  M        => Global_Variable);
                  if not LexTokenManager.Seq_Algebra.Is_Member
                    (The_Heap    => The_Heap,
                     S           => Exports,
                     Given_Value => Global_Variable_Val)
                    and then not LexTokenManager.Seq_Algebra.Is_Member
                    (The_Heap    => The_Heap,
                     S           => Imports,
                     Given_Value => Global_Variable_Val) then
                     LexTokenManager.Seq_Algebra.Remove_Member
                       (The_Heap    => The_Heap,
                        S           => Global_Variables (Unmoded),
                        Given_Value => Global_Variable_Val);
                  end if;
               end loop;
            end Remove_Excluded_Export;

            procedure Add_Modes
              (The_Heap              : in out Heap.HeapRecord;
               Function_Or_Procedure : in     Subprogram.Subprogram_Type;
               Imports               : in     LexTokenManager.Seq_Algebra.Seq;
               Exports               : in     LexTokenManager.Seq_Algebra.Seq;
               Global_Variables      : in out Global_Variables_Type)
            --# global in     LexTokenManager.State;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out Statistics.TableUsage;
            --# derives Global_Variables      from *,
            --#                                    Function_Or_Procedure,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    The_Heap &
            --#         Statistics.TableUsage,
            --#         The_Heap              from *,
            --#                                    Exports,
            --#                                    Function_Or_Procedure,
            --#                                    Global_Variables,
            --#                                    Imports,
            --#                                    LexTokenManager.State,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    The_Heap;
            is

               procedure Add_Procedure_Modes
                 (The_Heap         : in out Heap.HeapRecord;
                  Imports          : in     LexTokenManager.Seq_Algebra.Seq;
                  Exports          : in     LexTokenManager.Seq_Algebra.Seq;
                  Global_Variables : in     Global_Variables_Type)
               --# global in     LexTokenManager.State;
               --#        in out Statistics.TableUsage;
               --# derives Statistics.TableUsage,
               --#         The_Heap              from *,
               --#                                    Exports,
               --#                                    Global_Variables,
               --#                                    Imports,
               --#                                    LexTokenManager.State,
               --#                                    The_Heap;
               is
                  Global_Variable     : LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Global_Variable_Val : LexTokenManager.Lex_String;
                  Revised_Mode        : Modes;
               begin

                  Global_Variable :=
                    LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                              S        => Global_Variables (Unmoded));

                  loop

                     Global_Variable_Val :=
                       LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                    M        => Global_Variable);

                     if LexTokenManager.Seq_Algebra.Is_Member
                       (The_Heap    => The_Heap,
                        S           => Imports,
                        Given_Value => Global_Variable_Val) then
                        if LexTokenManager.Seq_Algebra.Is_Member
                          (The_Heap    => The_Heap,
                           S           => Exports,
                           Given_Value => Global_Variable_Val) then
                           Revised_Mode := In_Out_Mode;
                        else
                           Revised_Mode := In_Mode;
                        end if;
                     elsif LexTokenManager.Seq_Algebra.Is_Member
                       (The_Heap    => The_Heap,
                        S           => Exports,
                        Given_Value => Global_Variable_Val) then
                        Revised_Mode := Out_Mode;
                     else
                        Revised_Mode := Unmoded;
                     end if;

                     Global_Variable := LexTokenManager.Seq_Algebra.Next_Member (The_Heap => The_Heap,
                                                                                 M        => Global_Variable);

                     if Revised_Mode /= Unmoded then
                        LexTokenManager.Seq_Algebra.Remove_Member
                          (The_Heap    => The_Heap,
                           S           => Global_Variables (Unmoded),
                           Given_Value => Global_Variable_Val);
                        LexTokenManager.Seq_Algebra.Add_Member
                          (The_Heap    => The_Heap,
                           S           => Global_Variables (Revised_Mode),
                           Given_Value => Global_Variable_Val);
                     end if;

                     exit when LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable);

                  end loop;

               end Add_Procedure_Modes;

               procedure Add_Function_Modes (The_Heap         : in out Heap.HeapRecord;
                                             Global_Variables : in out Global_Variables_Type)
               --# global in     LexTokenManager.State;
               --#        in     SparkFormatCommandLineData.Content;
               --#        in out Statistics.TableUsage;
               --# derives Global_Variables      from *,
               --#                                    SparkFormatCommandLineData.Content,
               --#                                    The_Heap &
               --#         Statistics.TableUsage,
               --#         The_Heap              from *,
               --#                                    Global_Variables,
               --#                                    LexTokenManager.State,
               --#                                    SparkFormatCommandLineData.Content,
               --#                                    The_Heap;
               is

                  procedure Copy
                    (The_Heap         : in out Heap.HeapRecord;
                     Global_Variables : in out Global_Variables_Type;
                     From_Mode        : in     Modes;
                     To_Mode          : in     Modes)
                  --# global in     LexTokenManager.State;
                  --#        in out Statistics.TableUsage;
                  --# derives Global_Variables      from *,
                  --#                                    From_Mode,
                  --#                                    The_Heap,
                  --#                                    To_Mode &
                  --#         Statistics.TableUsage,
                  --#         The_Heap              from *,
                  --#                                    From_Mode,
                  --#                                    Global_Variables,
                  --#                                    LexTokenManager.State,
                  --#                                    The_Heap,
                  --#                                    To_Mode;
                  is
                     From_List    : LexTokenManager.Seq_Algebra.Seq;
                     To_List      : LexTokenManager.Seq_Algebra.Seq;
                     Revised_List : LexTokenManager.Seq_Algebra.Seq;
                  begin
                     From_List := Global_Variables (From_Mode);
                     To_List   := Global_Variables (To_Mode);
                     LexTokenManager.Seq_Algebra.Union (The_Heap => The_Heap,
                                                        A        => From_List,
                                                        B        => To_List,
                                                        C        => Revised_List);
                     LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                                 S        => To_List);
                     LexTokenManager.Seq_Algebra.Reduction (The_Heap => The_Heap,
                                                            A        => From_List,
                                                            B        => Revised_List);
                     Global_Variables (From_Mode) := From_List;
                     Global_Variables (To_Mode)   := Revised_List;
                  end Copy;

               begin

                  case SparkFormatCommandLineData.Content.Default_Function_Mode is
                     when SparkFormatCommandLineData.Unmoded =>
                        Copy
                          (The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           From_Mode        => In_Mode,
                           To_Mode          => Unmoded);
                     when SparkFormatCommandLineData.In_Mode =>
                        Copy
                          (The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           From_Mode        => Unmoded,
                           To_Mode          => In_Mode);
                  end case;

               end Add_Function_Modes;

            begin
               case Function_Or_Procedure is
                  when Subprogram.Is_Unknown | Subprogram.Is_Procedure =>
                     Add_Procedure_Modes
                       (The_Heap         => The_Heap,
                        Imports          => Imports,
                        Exports          => Exports,
                        Global_Variables => Global_Variables);
                  when Subprogram.Is_Function =>
                     Add_Function_Modes (The_Heap         => The_Heap,
                                         Global_Variables => Global_Variables);
               end case;
            end Add_Modes;

            procedure Write_Global_Variable_Clauses
              (Output                : in     SPARK_IO.File_Type;
               Start_Col             : in     E_Strings.Positions;
               First_Global_Variable : in out Boolean;
               The_Heap              : in     Heap.HeapRecord;
               Global_Variables      : in     Global_Variables_Type;
               Mode                  : in     Modes)
            --# global in     Annotation.Start_String;
            --#        in     LexTokenManager.State;
            --#        in     SparkFormatCommandLineData.Content;
            --#        in out SPARK_IO.File_Sys;
            --# derives First_Global_Variable from *,
            --#                                    Global_Variables,
            --#                                    LexTokenManager.State,
            --#                                    Mode,
            --#                                    The_Heap &
            --#         SPARK_IO.File_Sys     from *,
            --#                                    Annotation.Start_String,
            --#                                    First_Global_Variable,
            --#                                    Global_Variables,
            --#                                    LexTokenManager.State,
            --#                                    Mode,
            --#                                    Output,
            --#                                    SparkFormatCommandLineData.Content,
            --#                                    Start_Col,
            --#                                    The_Heap;
            is

               Global_Variable : LexTokenManager.Seq_Algebra.Member_Of_Seq;
               The_Iterator    : SPARKProgram.Iteration.Iterator;

               procedure Write_Global_Variable
                 (Output                : in     SPARK_IO.File_Type;
                  Start_Col             : in     E_Strings.Positions;
                  First_Global_Variable : in out Boolean;
                  The_Heap              : in     Heap.HeapRecord;
                  Global_Variable       : in     LexTokenManager.Seq_Algebra.Member_Of_Seq;
                  Global_Variables      : in     Global_Variables_Type;
                  Mode                  : in     Modes)
               --# global in     Annotation.Start_String;
               --#        in     LexTokenManager.State;
               --#        in     SparkFormatCommandLineData.Content;
               --#        in out SPARK_IO.File_Sys;
               --# derives First_Global_Variable from * &
               --#         SPARK_IO.File_Sys     from *,
               --#                                    Annotation.Start_String,
               --#                                    First_Global_Variable,
               --#                                    Global_Variable,
               --#                                    Global_Variables,
               --#                                    LexTokenManager.State,
               --#                                    Mode,
               --#                                    Output,
               --#                                    SparkFormatCommandLineData.Content,
               --#                                    Start_Col,
               --#                                    The_Heap;
               is

                  procedure Write_Mode
                    (Output           : in SPARK_IO.File_Type;
                     Start_Col        : in E_Strings.Positions;
                     The_Heap         : in Heap.HeapRecord;
                     Global_Variables : in Global_Variables_Type;
                     Mode             : in Modes)
                  --# global in     SparkFormatCommandLineData.Content;
                  --#        in out SPARK_IO.File_Sys;
                  --# derives SPARK_IO.File_Sys from *,
                  --#                                Global_Variables,
                  --#                                Mode,
                  --#                                Output,
                  --#                                SparkFormatCommandLineData.Content,
                  --#                                Start_Col,
                  --#                                The_Heap;
                  is

                     function Mode_Col (Start_Col : E_Strings.Positions) return E_Strings.Positions
                     --# global in SparkFormatCommandLineData.Content;
                     is
                        Mode_Column : E_Strings.Positions;
                     begin
                        if SparkFormatCommandLineData.Content.Global_Indent >= 1 then
                           -- Start_Col "is --# " but indent value is given from "--#"
                           Mode_Column := Global_Col (Start_Col => Start_Col) +
                             (SparkFormatCommandLineData.Content.Global_Indent - 1);
                        else
                           Mode_Column := Global_Col (Start_Col => Start_Col) + 7; -- length of "global "
                        end if;
                        return Mode_Column;
                     end Mode_Col;

                  begin

                     SPARK_IO.Set_Col (Output, Mode_Col (Start_Col => Start_Col));

                     case Mode is
                        when In_Mode =>
                           SPARK_IO.Put_String (Output, "in ", 0);
                           if not (LexTokenManager.Seq_Algebra.Is_Empty_Seq
                                     (The_Heap => The_Heap,
                                      S        => Global_Variables (In_Out_Mode))
                                     and then LexTokenManager.Seq_Algebra.Is_Empty_Seq
                                     (The_Heap => The_Heap,
                                      S        => Global_Variables (Out_Mode))) then
                              SPARK_IO.Put_String (Output, "    ", 0);
                           end if;
                        when Out_Mode =>
                           if not (LexTokenManager.Seq_Algebra.Is_Empty_Seq
                                     (The_Heap => The_Heap,
                                      S        => Global_Variables (In_Mode))
                                     and then LexTokenManager.Seq_Algebra.Is_Empty_Seq
                                     (The_Heap => The_Heap,
                                      S        => Global_Variables (In_Out_Mode))) then
                              SPARK_IO.Put_String (Output, "   ", 0);
                           end if;
                           SPARK_IO.Put_String (Output, "out ", 0);
                        when In_Out_Mode =>
                           SPARK_IO.Put_String (Output, "in out ", 0);
                        when Unmoded =>
                           null;
                     end case;

                  end Write_Mode;

               begin  -- Write_Global_Variable

                  if First_Global_Variable then
                     First_Global_Variable := False;
                     if SparkFormatCommandLineData.Content.Global_Indent >= 1 then
                        Annotation.Write (Output    => Output,
                                          Start_Col => Start_Col);
                     end if;
                  else
                     case Mode is
                        when Unmoded =>
                           SPARK_IO.Put_Line (Output, ",", 0);
                        when In_Mode | Out_Mode | In_Out_Mode =>
                           SPARK_IO.Put_Line (Output, ";", 0);
                     end case;
                     Annotation.Write (Output    => Output,
                                       Start_Col => Start_Col);
                  end if;

                  Write_Mode
                    (Output           => Output,
                     Start_Col        => Start_Col,
                     The_Heap         => The_Heap,
                     Global_Variables => Global_Variables,
                     Mode             => Mode);
                  E_Strings.Put_String
                    (File  => Output,
                     E_Str => LexTokenManager.Lex_String_To_String
                       (Lex_Str => LexTokenManager.Seq_Algebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                M        => Global_Variable)));
               end Write_Global_Variable;

            begin -- Write_Global_Variable_Clauses

               -- This subprogram is called for each mode in turn.
               -- Each sequence of global variables could be null, in which case we don't write anything
               -- for that mode.
               Global_Variable := LexTokenManager.Seq_Algebra.First_Member (The_Heap => The_Heap,
                                                                            S        => Global_Variables (Mode));

               if not LexTokenManager.Seq_Algebra.Is_Null_Member (M => Global_Variable) then

                  SPARKProgram.Iteration.Initialise
                    (The_Heap     => The_Heap,
                     The_Seq      => Global_Variables (Mode),
                     The_Iterator => The_Iterator);

                  Write_Global_Variable
                    (Output                => Output,
                     Start_Col             => Start_Col,
                     First_Global_Variable => First_Global_Variable,
                     The_Heap              => The_Heap,
                     Global_Variable       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator),
                     Global_Variables      => Global_Variables,
                     Mode                  => Mode);

                  SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                               The_Iterator => The_Iterator);

                  while not SPARKProgram.Iteration.Complete (The_Iterator => The_Iterator) loop

                     Write_Global_Variable
                       (Output                => Output,
                        Start_Col             => Start_Col,
                        First_Global_Variable => First_Global_Variable,
                        The_Heap              => The_Heap,
                        Global_Variable       => SPARKProgram.Iteration.Current_Member (The_Iterator => The_Iterator),
                        Global_Variables      => Global_Variables,
                        Mode                  => Mode);

                     SPARKProgram.Iteration.Next (The_Heap     => The_Heap,
                                                  The_Iterator => The_Iterator);

                  end loop;

               end if;

            end Write_Global_Variable_Clauses;

            procedure Dispose (The_Heap         : in out Heap.HeapRecord;
                               Global_Variables : in     Global_Variables_Type)
            --# derives The_Heap from *,
            --#                       Global_Variables;
            is
            begin
               for Mode in Modes loop
                  LexTokenManager.Seq_Algebra.Dispose_Of_Seq (The_Heap => The_Heap,
                                                              S        => Global_Variables (Mode));
               end loop;
            end Dispose;

         begin -- Globals_List.Reformat

            Revised_Global_Variables := Global_Variables;

            if OK then

               --  CFR1753: Check to see if an export has been excluded.
               An_Export_Is_Excluded := not E_Strings.Is_Empty (E_Str => SparkFormatCommandLineData.Content.Exclude_Export);
               case Function_Or_Procedure is
                  when Subprogram.Is_Procedure | Subprogram.Is_Unknown =>
                     if An_Export_Is_Excluded then
                        Remove_Excluded_Export
                          (The_Heap         => The_Heap,
                           Imports          => Imports,
                           Exports          => Exports,
                           Global_Variables => Revised_Global_Variables);
                     end if;
                  when Subprogram.Is_Function =>
                     null;
               end case;

               if not An_Export_Is_Excluded
                 or else not LexTokenManager.Seq_Algebra.Is_Empty_Seq
                 (The_Heap => The_Heap,
                  S        => Revised_Global_Variables (Out_Mode))
                 or else not LexTokenManager.Seq_Algebra.Is_Empty_Seq
                 (The_Heap => The_Heap,
                  S        => Revised_Global_Variables (In_Out_Mode))
                 or else not LexTokenManager.Seq_Algebra.Is_Empty_Seq
                 (The_Heap => The_Heap,
                  S        => Revised_Global_Variables (In_Mode))
                 or else not LexTokenManager.Seq_Algebra.Is_Empty_Seq
                 (The_Heap => The_Heap,
                  S        => Revised_Global_Variables (Unmoded)) then
                  Annotation.Write (Output    => Output,
                                    Start_Col => Start_Col);
                  Write_Global (Output    => Output,
                                Start_Col => Start_Col);

                  if SparkFormatCommandLineData.Content.Add_Modes then
                     Add_Modes
                       (The_Heap              => The_Heap,
                        Function_Or_Procedure => Function_Or_Procedure,
                        Imports               => Imports,
                        Exports               => Exports,
                        Global_Variables      => Revised_Global_Variables);
                  end if;

                  First_Global_Variable := True;

                  for Mode in Modes loop
                     Write_Global_Variable_Clauses
                       (Output                => Output,
                        Start_Col             => Start_Col,
                        First_Global_Variable => First_Global_Variable,
                        The_Heap              => The_Heap,
                        Global_Variables      => Revised_Global_Variables,
                        Mode                  => Mode);
                  end loop;

                  SPARK_IO.Put_Line (Output, ";", 0);
               end if;
            else
               File_IO.Reset (Temporary_File => Temporary_File);
               SPARKProgram.Copy (Input  => Temporary_File,
                                  Output => Output);
            end if;

            Dispose (The_Heap         => The_Heap,
                     Global_Variables => Revised_Global_Variables);
            File_IO.Delete (Temporary_File => Temporary_File);

            if not No_Empty_Lines then
               SPARK_IO.New_Line (Output, Consecutive_Empty_Lines);
            end if;
            Reset_Consecutive_Empty_Lines;
         end Reformat;

      end Globals_List;

      function Contains_Function_Specification (Input_Line : E_Strings.T) return Boolean is
         Index : E_Strings.Positions;
      begin

         Index := E_Strings.Positions'First;
         White_Space.Skip (Input_Line => Input_Line,
                           Index      => Index);

         return E_Strings.Get_Element (E_Str => Input_Line,
                                       Pos   => Index) = 'f'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 1) = 'u'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 2) = 'n'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 3) = 'c'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 4) = 't'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 5) = 'i'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 6) = 'o'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 7) = 'n';

      end Contains_Function_Specification;

      function Contains_Procedure_Specification (Input_Line : E_Strings.T) return Boolean is
         Index : E_Strings.Positions;
      begin

         Index := E_Strings.Positions'First;
         White_Space.Skip (Input_Line => Input_Line,
                           Index      => Index);

         return E_Strings.Get_Element (E_Str => Input_Line,
                                       Pos   => Index) = 'p'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 1) = 'r'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 2) = 'o'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 3) = 'c'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 4) = 'e'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 5) = 'd'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 6) = 'u'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 7) = 'r'
           and then E_Strings.Get_Element (E_Str => Input_Line,
                                           Pos   => Index + 8) = 'e';

      end Contains_Procedure_Specification;

   begin  -- Reformat_Annotations

      State                 := Parsing_SPARK_Code;
      Globals_List_File     := SPARK_IO.Null_File;
      Inherit_Clause_File   := SPARK_IO.Null_File;
      Initialize_Spec_File  := SPARK_IO.Null_File;
      Own_Var_Clause_File   := SPARK_IO.Null_File;
      Derives_List_File     := SPARK_IO.Null_File;
      Function_Or_Procedure := Subprogram.Is_Unknown;

      Heap.Initialize (The_Heap);
      SparkLex.Clear_Line_Context;
      Annotation.Initialize;
      Derives_List.Initialize;

      Annotations.Initialize
        (This        => Inherit_Anno,
         Anno_Intro  => "inherit",
         Anno_Succ   => "main_program",
         Anno_Indent => SparkFormatCommandLineData.Content.Inherit_Indent);

      Annotations.Initialize
        (This        => Initializes_Anno,
         Anno_Intro  => "initializes",
         Anno_Succ   => "",
         Anno_Indent => SparkFormatCommandLineData.Content.Initialization_Indent);

      Annotations.Initialize
        (This        => Own_Var_Anno,
         Anno_Intro  => "own",
         Anno_Succ   => "initializes",
         Anno_Indent => SparkFormatCommandLineData.Content.Own_Indent);

      if not SPARK_IO.End_Of_File (Input) then
         E_Strings.Get_Line (File  => Input,
                             E_Str => Input_Line);
         File_IO_Required := False;

         while not (File_IO_Required and then SPARK_IO.End_Of_File (Input)) loop

            if File_IO_Required then
               E_Strings.Get_Line (File  => Input,
                                   E_Str => Input_Line);
            else
               File_IO_Required := True;
            end if;

            case State is
               when Parsing_SPARK_Code =>
                  if Contains_Function_Specification (Input_Line => Input_Line) then
                     E_Strings.Put_Line (File  => Output,
                                         E_Str => Input_Line);
                     Function_Or_Procedure := Subprogram.Is_Function;
                  elsif Contains_Procedure_Specification (Input_Line => Input_Line) then
                     E_Strings.Put_Line (File  => Output,
                                         E_Str => Input_Line);
                     Function_Or_Procedure := Subprogram.Is_Procedure;
                  elsif Globals_List.Is_Start (Input_Line => Input_Line) then
                     File_IO.Create (Temporary_File => Globals_List_File);
                     E_Strings.Put_Line (File  => Globals_List_File,
                                         E_Str => Input_Line);
                     if SPARK_IO.End_Of_File (Input) then
                        -- This route only taken when global alone at end of file
                        Globals_List.Parse
                          (Temporary_File   => Globals_List_File,
                           Start_Col        => Start_Col,
                           The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           OK               => Globals_List_OK);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Imports);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Exports);
                        Globals_List.Reformat
                          (OK                    => Globals_List_OK,
                           Temporary_File        => Globals_List_File,
                           Output                => Output,
                           Start_Col             => Start_Col,
                           The_Heap              => The_Heap,
                           Function_Or_Procedure => Function_Or_Procedure,
                           Global_Variables      => Global_Variables,
                           Imports               => Imports,
                           Exports               => Exports);
                        Function_Or_Procedure := Subprogram.Is_Unknown;
                     else
                        -- Normal route
                        State := Parsing_Globals_List;
                     end if;
                  elsif Derives_List.Is_Start (Input_Line => Input_Line) then
                     File_IO.Create (Temporary_File => Derives_List_File);
                     E_Strings.Put_Line (File  => Derives_List_File,
                                         E_Str => Input_Line);
                     if Derives_List.Is_End (Input_Line => Input_Line) then
                        --# accept Flow_Message, 10, Imports, "There is no globals list, so no need for the list of imports.";
                        Derives_List.Parse
                          (Temporary_File => Derives_List_File,
                           Start_Col      => Start_Col,
                           The_Heap       => The_Heap,
                           Imports        => Imports,
                           Exports        => Exports,
                           Dependencies   => Dependencies,
                           OK             => Derives_List_OK);
                        --# end accept;
                        Derives_List.Reformat
                          (OK             => Derives_List_OK,
                           Temporary_File => Derives_List_File,
                           Output         => Output,
                           Start_Col      => Start_Col,
                           The_Heap       => The_Heap,
                           Exports        => Exports,
                           Dependencies   => Dependencies);
                        Function_Or_Procedure := Subprogram.Is_Unknown;
                     elsif SPARK_IO.End_Of_File (Input) then
                        File_IO.Reset (Temporary_File => Derives_List_File);
                        Copy (Input  => Derives_List_File,
                              Output => Output);
                        Function_Or_Procedure := Subprogram.Is_Unknown;
                     else
                        State := Parsing_Derives_List;
                     end if;
                  elsif Annotations.Is_Start_Of (This       => Inherit_Anno,
                                                 Input_Line => Input_Line) then
                     File_IO.Create (Temporary_File => Inherit_Clause_File);
                     State            := Parsing_Inherit_Clause;
                     File_IO_Required := False;
                  elsif Annotations.Is_Start_Of (This       => Initializes_Anno,
                                                 Input_Line => Input_Line) then
                     File_IO.Create (Temporary_File => Initialize_Spec_File);
                     State            := Parsing_Initialization_Specification;
                     File_IO_Required := False;
                  elsif Annotations.Is_Start_Of (This       => Own_Var_Anno,
                                                 Input_Line => Input_Line) then
                     File_IO.Create (Temporary_File => Own_Var_Clause_File);
                     State            := Parsing_Own_Variable_Clause;
                     File_IO_Required := False;
                  else
                     E_Strings.Put_Line (File  => Output,
                                         E_Str => Input_Line);
                  end if;
               when Parsing_Globals_List =>
                  if Globals_List.Is_End (Input_Line => Input_Line) then
                     if Derives_List.Is_Start (Input_Line => Input_Line) then
                        if Globals_List.No_Empty_Lines then
                           File_IO.Create (Temporary_File => Derives_List_File);
                           E_Strings.Put_Line (File  => Derives_List_File,
                                               E_Str => Input_Line);
                           if Derives_List.Is_End (Input_Line => Input_Line) then
                              --# accept F, 10, SparkLex.Curr_Line,
                              --#        "Not used when both global and derives lists present" &
                              --#        F, 10, Start_Col,
                              --#        "If both globals and derives lists present, Start_Col value from derives list is used";
                              Globals_List.Parse
                                (Temporary_File   => Globals_List_File,
                                 Start_Col        => Start_Col,
                                 The_Heap         => The_Heap,
                                 Global_Variables => Global_Variables,
                                 OK               => Globals_List_OK);
                              --# end accept;
                              Derives_List.Parse
                                (Temporary_File => Derives_List_File,
                                 Start_Col      => Start_Col,
                                 The_Heap       => The_Heap,
                                 Imports        => Imports,
                                 Exports        => Exports,
                                 Dependencies   => Dependencies,
                                 OK             => Derives_List_OK);
                              Globals_List.Reformat
                                (OK                    => Globals_List_OK,
                                 Temporary_File        => Globals_List_File,
                                 Output                => Output,
                                 Start_Col             => Start_Col,
                                 The_Heap              => The_Heap,
                                 Function_Or_Procedure => Function_Or_Procedure,
                                 Global_Variables      => Global_Variables,
                                 Imports               => Imports,
                                 Exports               => Exports);
                              Derives_List.Reformat
                                (OK             => Derives_List_OK,
                                 Temporary_File => Derives_List_File,
                                 Output         => Output,
                                 Start_Col      => Start_Col,
                                 The_Heap       => The_Heap,
                                 Exports        => Exports,
                                 Dependencies   => Dependencies);
                              Function_Or_Procedure := Subprogram.Is_Unknown;
                              State                 := Parsing_SPARK_Code;
                           else
                              State := Parsing_Derives_List;
                           end if;
                        else
                           Globals_List.Parse
                             (Temporary_File   => Globals_List_File,
                              Start_Col        => Start_Col,
                              The_Heap         => The_Heap,
                              Global_Variables => Global_Variables,
                              OK               => Globals_List_OK);
                           LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                   S        => Imports);
                           LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                   S        => Exports);
                           Globals_List.Reformat
                             (OK                    => Globals_List_OK,
                              Temporary_File        => Globals_List_File,
                              Output                => Output,
                              Start_Col             => Start_Col,
                              The_Heap              => The_Heap,
                              Function_Or_Procedure => Function_Or_Procedure,
                              Global_Variables      => Global_Variables,
                              Imports               => Imports,
                              Exports               => Exports);
                           State            := Parsing_SPARK_Code;
                           File_IO_Required := False;
                        end if;
                     else
                        Globals_List.Parse
                          (Temporary_File   => Globals_List_File,
                           Start_Col        => Start_Col,
                           The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           OK               => Globals_List_OK);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Imports);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Exports);
                        Globals_List.Reformat
                          (OK                    => Globals_List_OK,
                           Temporary_File        => Globals_List_File,
                           Output                => Output,
                           Start_Col             => Start_Col,
                           The_Heap              => The_Heap,
                           Function_Or_Procedure => Function_Or_Procedure,
                           Global_Variables      => Global_Variables,
                           Imports               => Imports,
                           Exports               => Exports);
                        Function_Or_Procedure := Subprogram.Is_Unknown;
                        State                 := Parsing_SPARK_Code;
                        File_IO_Required      := False; -- Have another look at line in case is a function
                     end if;
                  elsif SPARK_IO.End_Of_File (Input) then
                     E_Strings.Put_Line (File  => Globals_List_File,
                                         E_Str => Input_Line);
                     Globals_List.Parse
                       (Temporary_File   => Globals_List_File,
                        Start_Col        => Start_Col,
                        The_Heap         => The_Heap,
                        Global_Variables => Global_Variables,
                        OK               => Globals_List_OK);
                     LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                             S        => Imports);
                     LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                             S        => Exports);
                     Globals_List.Reformat
                       (OK                    => Globals_List_OK,
                        Temporary_File        => Globals_List_File,
                        Output                => Output,
                        Start_Col             => Start_Col,
                        The_Heap              => The_Heap,
                        Function_Or_Procedure => Function_Or_Procedure,
                        Global_Variables      => Global_Variables,
                        Imports               => Imports,
                        Exports               => Exports);
                     Function_Or_Procedure := Subprogram.Is_Unknown;
                     State                 := Parsing_SPARK_Code;
                  else
                     E_Strings.Put_Line (File  => Globals_List_File,
                                         E_Str => Input_Line);
                     if E_Strings.Is_Empty (E_Str => E_Strings.Trim (Input_Line)) then
                        Globals_List.Increment_Consecutive_Empty_Lines;
                     else
                        Globals_List.Reset_Consecutive_Empty_Lines;
                     end if;
                  end if;
               when Parsing_Derives_List =>
                  E_Strings.Put_Line (File  => Derives_List_File,
                                      E_Str => Input_Line);
                  if Derives_List.Is_End (Input_Line => Input_Line) then
                     Derives_List.Parse
                       (Temporary_File => Derives_List_File,
                        Start_Col      => Start_Col,
                        The_Heap       => The_Heap,
                        Imports        => Imports,
                        Exports        => Exports,
                        Dependencies   => Dependencies,
                        OK             => Derives_List_OK);
                     if SPARK_IO.Is_Open (Globals_List_File) then
                        Globals_List.Parse
                          (Temporary_File   => Globals_List_File,
                           Start_Col        => Start_Col,
                           The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           OK               => Globals_List_OK);
                        Globals_List.Reformat
                          (OK                    => Globals_List_OK,
                           Temporary_File        => Globals_List_File,
                           Output                => Output,
                           Start_Col             => Start_Col,
                           The_Heap              => The_Heap,
                           Function_Or_Procedure => Function_Or_Procedure,
                           Global_Variables      => Global_Variables,
                           Imports               => Imports,
                           Exports               => Exports);
                     end if;
                     Derives_List.Reformat
                       (OK             => Derives_List_OK,
                        Temporary_File => Derives_List_File,
                        Output         => Output,
                        Start_Col      => Start_Col,
                        The_Heap       => The_Heap,
                        Exports        => Exports,
                        Dependencies   => Dependencies);
                     Function_Or_Procedure := Subprogram.Is_Unknown;
                     State                 := Parsing_SPARK_Code;
                  elsif SPARK_IO.End_Of_File (Input) then
                     if SPARK_IO.Is_Open (Globals_List_File) then
                        Globals_List.Parse
                          (Temporary_File   => Globals_List_File,
                           Start_Col        => Start_Col,
                           The_Heap         => The_Heap,
                           Global_Variables => Global_Variables,
                           OK               => Globals_List_OK);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Imports);
                        LexTokenManager.Seq_Algebra.Create_Seq (The_Heap => The_Heap,
                                                                S        => Exports);
                        Globals_List.Reformat
                          (OK                    => Globals_List_OK,
                           Temporary_File        => Globals_List_File,
                           Output                => Output,
                           Start_Col             => Start_Col,
                           The_Heap              => The_Heap,
                           Function_Or_Procedure => Function_Or_Procedure,
                           Global_Variables      => Global_Variables,
                           Imports               => Imports,
                           Exports               => Exports);
                     end if;
                     File_IO.Reset (Temporary_File => Derives_List_File);
                     Copy (Input  => Derives_List_File,
                           Output => Output);
                     Function_Or_Procedure := Subprogram.Is_Unknown;
                     State                 := Parsing_SPARK_Code;
                  end if;
               when Parsing_Inherit_Clause =>
                  E_Strings.Put_Line (File  => Inherit_Clause_File,
                                      E_Str => Input_Line);

                  if Annotations.Is_End_Of (This       => Inherit_Anno,
                                            Input_Line => Input_Line)
                    or else SPARK_IO.End_Of_File (Input) then
                     Reformatter.Initialise
                       (Anno         => Inherit_Anno,
                        Dotted_Names => Reformatter.Allow_Dotted_Names_Const,
                        The_Heap     => The_Heap,
                        This         => Inherit_Clause);
                     Reformatter.Parse (This           => Inherit_Clause,
                                        The_Heap       => The_Heap,
                                        Temporary_File => Inherit_Clause_File);
                     Reformatter.Reformat
                       (This           => Inherit_Clause,
                        The_Heap       => The_Heap,
                        Temporary_File => Inherit_Clause_File,
                        Output         => Output,
                        Success        => Reformat_Successful);
                     --# accept F, 10, Inherit_Clause,
                     --#        "The state variable has been 'disposed' and should not be reused without initialisation";
                     Reformatter.Finalise (This     => Inherit_Clause,
                                           The_Heap => The_Heap);
                     --# end accept;
                     File_IO.Delete (Temporary_File => Inherit_Clause_File);
                     State            := Parsing_SPARK_Code;
                     File_IO_Required := not Reformat_Successful;
                  end if;
               when Parsing_Initialization_Specification =>
                  E_Strings.Put_Line (File  => Initialize_Spec_File,
                                      E_Str => Input_Line);

                  if Annotations.Is_End_Of (This       => Initializes_Anno,
                                            Input_Line => Input_Line)
                    or else SPARK_IO.End_Of_File (Input) then
                     Reformatter.Initialise
                       (Anno         => Initializes_Anno,
                        Dotted_Names => Reformatter.Disallow_Dotted_Names_Const,
                        The_Heap     => The_Heap,
                        This         => Initialization_Spec);
                     Reformatter.Parse (This           => Initialization_Spec,
                                        The_Heap       => The_Heap,
                                        Temporary_File => Initialize_Spec_File);
                     Reformatter.Reformat
                       (This           => Initialization_Spec,
                        The_Heap       => The_Heap,
                        Temporary_File => Initialize_Spec_File,
                        Output         => Output,
                        Success        => Reformat_Successful);
                     --# accept F, 10, Initialization_Spec,
                     --#        "The state variable has been 'disposed' and should not be reused without initialisation";
                     Reformatter.Finalise (This     => Initialization_Spec,
                                           The_Heap => The_Heap);
                     --# end accept;
                     File_IO.Delete (Temporary_File => Initialize_Spec_File);
                     State            := Parsing_SPARK_Code;
                     File_IO_Required := not Reformat_Successful;
                  end if;
               when Parsing_Own_Variable_Clause =>
                  E_Strings.Put_Line (File  => Own_Var_Clause_File,
                                      E_Str => Input_Line);

                  if Annotations.Is_End_Of (This       => Own_Var_Anno,
                                            Input_Line => Input_Line)
                    or else SPARK_IO.End_Of_File (Input) then
                     Reformatter.Initialise
                       (Anno         => Own_Var_Anno,
                        Dotted_Names => Reformatter.Disallow_Dotted_Names_Const,
                        The_Heap     => The_Heap,
                        This         => Own_Variable_Clause);
                     Reformatter.Parse (This           => Own_Variable_Clause,
                                        The_Heap       => The_Heap,
                                        Temporary_File => Own_Var_Clause_File);
                     Reformatter.Reformat
                       (This           => Own_Variable_Clause,
                        The_Heap       => The_Heap,
                        Temporary_File => Own_Var_Clause_File,
                        Output         => Output,
                        Success        => Reformat_Successful);
                     --# accept F, 10, Own_Variable_Clause,
                     --#        "The state variable has been 'disposed' and should not be reused without initialisation";
                     Reformatter.Finalise (This     => Own_Variable_Clause,
                                           The_Heap => The_Heap);
                     --# end accept;
                     File_IO.Delete (Temporary_File => Own_Var_Clause_File);
                     State            := Parsing_SPARK_Code;
                     File_IO_Required := not Reformat_Successful;
                  end if;

               when Parsing_Refinement_Definition =>
                  -- To be completed
                  State := Parsing_SPARK_Code;

            end case;

         end loop;
      end if;

   end Reformat_Annotations;

end SPARKProgram;
