-------------------------------------------------------------------------------
-- (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 SPARK_IO, CommandLineData; -- used for trace/debug statements only, not inherited

with SP_Symbols;
with SystemErrors;

use type SP_Symbols.SP_Symbol;

package body RequiredUnits is

   -- Following hidden trace routine enabled by -debug=u -----------------------------------
   procedure Trace (Msg : String)
   --# derives null from Msg;
   is
      --# hide Trace;
   begin
      if CommandLineData.Content.Debug.Units then
         SPARK_IO.Put_Line (SPARK_IO.Standard_Output, Msg, 0);
      end if;
   end Trace;

   ------------------------------------------------------------------------------------------

   procedure Init
     (Top_Node    : in     STree.SyntaxNode;
      Inherit_Ptr :    out STree.SyntaxNode;
      Unit_Type   :    out ContextManager.UnitTypes;
      Unit_Name   :    out LexTokenLists.Lists)
   is
      Inherit_Ptr_Local, Name_Ptr : STree.SyntaxNode;
      Unit_Type_Local             : ContextManager.UnitTypes;
      Unit_Name_Local             : LexTokenLists.Lists;
   begin
      -- ASSUME Top_Node = compilation_unit
      SystemErrors.RT_Assert
        (C       => STree.Syntax_Node_Type (Node => Top_Node) = SP_Symbols.compilation_unit,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Top_Node = compilation_unit in RequiredUnits.Init");

      -- compilation_unit :
      --      context_clause library_unit
      --    | context_clause secondary_unit
      --    | library_unit
      --    | secondary_unit
      --    | apragma
      --    | ;

      Trace ("Entering RequiredUnits.Init");
      Inherit_Ptr_Local := STree.Child_Node (Current_Node => Top_Node);
      if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.context_clause then
         Inherit_Ptr_Local := STree.Next_Sibling (Current_Node => Inherit_Ptr_Local);
      end if;
      -- any WITH clause [and/or use type clause] now skipped

      -- ASSUME Inherit_Ptr_Local = library_unit OR secondary_unit OR apragma OR SPend
      if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.library_unit then
         -- ASSUME Inherit_Ptr_Local = library_unit
         Trace ("   library unit found");
         Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
         -- ASSUME Inherit_Ptr_Local = package_declaration OR private_package_declaration OR main_program_declaration OR
         --                            generic_declaration OR generic_package_instantiation
         if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.package_declaration
           or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.private_package_declaration then
            -- ASSUME Inherit_Ptr_Local = package_declaration OR private_package_declaration
            Trace ("   package declaration found");
            Unit_Type_Local   := ContextManager.PackageSpecification;
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = package_specification OR inherit_clause
            if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.inherit_clause then
               Name_Ptr := STree.Next_Sibling (Current_Node => Inherit_Ptr_Local);
            elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.package_specification then
               Name_Ptr          := Inherit_Ptr_Local;
               Inherit_Ptr_Local := STree.NullNode;
            else
               Name_Ptr          := STree.NullNode;
               Inherit_Ptr_Local := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Inherit_Ptr_Local = package_specification OR inherit_clause in RequiredUnits.Init");
            end if;
            -- ASSUME Name_Ptr = package_specification
            SystemErrors.RT_Assert
              (C       => STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.package_specification,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Name_Ptr = compilation_unit in RequiredUnits.Init");
            Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
            -- ASSUME Inherit_Ptr_Local = inherit_clause OR NULL
            -- ASSUME Name_Ptr = dotted_simple_name
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.main_program_declaration then
            -- ASSUME Inherit_Ptr_Local = main_program_declaration
            Trace ("   main program found");
            Unit_Type_Local   := ContextManager.MainProgram;
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = inherit_clause OR main_program_annotation
            if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.inherit_clause then
               Name_Ptr := STree.Next_Sibling (Current_Node => Inherit_Ptr_Local);
            elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.main_program_annotation then
               Name_Ptr          := Inherit_Ptr_Local;
               Inherit_Ptr_Local := STree.NullNode;
            else
               Name_Ptr          := STree.NullNode;
               Inherit_Ptr_Local := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Inherit_Ptr_Local = inherit_clause OR main_program_annotation in RequiredUnits.Init");
            end if;
            -- ASSUME Name_Ptr = main_program_annotation
            SystemErrors.RT_Assert
              (C       => STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.main_program_annotation,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Name_Ptr = main_program_annotation in RequiredUnits.Init");
            Name_Ptr :=
              STree.Child_Node
              (Current_Node => STree.Child_Node
                 (Current_Node => STree.Child_Node (Current_Node => STree.Last_Sibling_Of (Start_Node => Name_Ptr))));
            -- ASSUME Inherit_Ptr_Local = inherit_clause OR NULL
            -- ASSUME Name_Ptr = identifier
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_declaration then
            -- ASSUME Inherit_Ptr_Local = generic_declaration
            Trace ("   generic declaration  found");
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = generic_subprogram_declaration OR generic_package_declaration
            if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_subprogram_declaration then
               -- ASSUME Inherit_Ptr_Local = generic_subprogram_declaration
               Unit_Type_Local := ContextManager.GenericSubprogramDeclaration;
            elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_package_declaration then
               Unit_Type_Local := ContextManager.PackageSpecification;
            else
               Unit_Type_Local := ContextManager.InvalidUnit;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Inherit_Ptr_Local = generic_subprogram_declaration OR " &
                    "generic_package_declaration in RequiredUnits.Init");
            end if;
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = inherit_clause OR generic_formal_part
            if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.inherit_clause then
               Name_Ptr := STree.Next_Sibling (Current_Node => Inherit_Ptr_Local);
            elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_formal_part then
               Name_Ptr          := Inherit_Ptr_Local;
               Inherit_Ptr_Local := STree.NullNode;
            else
               Name_Ptr          := STree.NullNode;
               Inherit_Ptr_Local := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Inherit_Ptr_Local = inherit_clause OR generic_formal_part in RequiredUnits.Init");
            end if;
            -- ASSUME Name_Ptr = generic_formal_part
            SystemErrors.RT_Assert
              (C       => STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.generic_formal_part,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Name_Ptr = generic_formal_part in RequiredUnits.Init");
            Name_Ptr := STree.Next_Sibling (Current_Node => Name_Ptr);
            -- ASSUME Name_Ptr = not_overriding_subprogram_declaration OR package_specification
            if STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.package_specification then
               -- ASSUME Name_Ptr = package_specification
               Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
            elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.not_overriding_subprogram_declaration then
               -- ASSUME Name_Ptr = not_overriding_subprogram_declaration
               Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
               -- ASSUME Name_Ptr = procedure_specification OR function_specification OR proof_function_declaration
               if STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.proof_function_declaration then
                  -- ASSUME Name_Ptr = proof_function_declaration
                  Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
               elsif STree.Syntax_Node_Type (Node => Name_Ptr) /= SP_Symbols.procedure_specification
                 and then STree.Syntax_Node_Type (Node => Name_Ptr) /= SP_Symbols.function_specification then
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Name_Ptr = procedure_specification OR function_specification OR " &
                       "proof_function_declaration in RequiredUnits.Init");
               end if;
               -- ASSUME Name_Ptr = procedure_specification OR function_specification
               SystemErrors.RT_Assert
                 (C       => STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.procedure_specification
                    or else STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.function_specification,
                  Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Name_Ptr = procedure_specification OR function_specification in RequiredUnits.Init");
               Name_Ptr := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Name_Ptr));
            else
               Name_Ptr := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Name_Ptr = not_overriding_subprogram_declaration OR " &
                    "package_specification in RequiredUnits.Init");
            end if;
            -- ASSUME Inherit_Ptr_Local = inherit_clause OR NULL
            -- ASSUME Name_Ptr = dotted_simple_name OR identifier
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_package_instantiation then
            -- ASSUME Inherit_Ptr_Local = generic_package_instantiation

            -- generic_package_instantiation :
            --      dotted_simple_name package_annotation RWis RWnew identifier generic_actual_part semicolon
            --    | dotted_simple_name package_annotation RWis RWnew identifier                     semicolon ;

            Trace ("   generic declaration found");
            Unit_Type_Local   := ContextManager.PackageSpecification;
            Name_Ptr          := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            Inherit_Ptr_Local := STree.NullNode;
            -- ASSUME Inherit_Ptr_Local = NULL
            -- ASSUME Name_Ptr = dotted_simple_name

            -- add elsif here for generic subprog bods

         else
            Unit_Type_Local   := ContextManager.InvalidUnit;
            Name_Ptr          := STree.NullNode;
            Inherit_Ptr_Local := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Inherit_Ptr_Local = package_declaration OR private_package_declaration OR " &
                 "main_program_declaration OR generic_declaration OR generic_package_instantiation in RequiredUnits.Init");
         end if;
         -- ASSUME Inherit_Ptr_Local = inherit_clause OR NULL
         if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.inherit_clause then
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Inherit_Ptr_Local));
         end if;
         -- ASSUME Inherit_Ptr_Local = inherit_clause_rep OR dotted_simple_name OR NULL
         -- ASSUME Name_Ptr = dotted_simple_name OR identifier
      elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.secondary_unit then
         -- ASSUME Inherit_Ptr_Local = secondary_unit

         -- secondary_unit :
         --      library_unit_body | subunit ;

         Trace ("   secondary unit found");
         Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
         -- ASSUME Inherit_Ptr_Local = library_unit_body OR subunit
         if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.library_unit_body then
            -- ASSUME Inherit_Ptr_Local = library_unit_body

            -- library_unit_body :
            --      package_body | generic_subprogram_body ;

            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = package_body OR generic_subprogram_body
            if STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.package_body then
               -- ASSUME Inherit_Ptr_Local = package_body

               -- package_body :
               --      RWpackage RWbody dotted_simple_name                       RWis package_implementation semicolon
               --    | RWpackage RWbody dotted_simple_name refinement_definition RWis package_implementation semicolon ;

               Trace ("   package body found");
               Unit_Type_Local   := ContextManager.PackageBody;
               Name_Ptr          := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
               Inherit_Ptr_Local := STree.NullNode;
               -- ASSUME Inherit_Ptr_Local = NULL
               -- ASSUME Name_Ptr = dotted_simple_name
            elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.generic_subprogram_body then
               -- ASSUME Inherit_Ptr_Local = generic_subprogram_body

               -- generic_subprogram_body :
               --      not_overriding_subprogram_body ;
               --
               -- not_overriding_subprogram_body :
               --      procedure_specification procedure_annotation subprogram_implementation
               --    | function_specification  function_annotation  subprogram_implementation ;
               --
               -- procedure_specification :
               --      RWprocedure designator
               --    | RWprocedure designator formal_part ;
               --
               -- function_specification :
               --      RWfunction designator formal_part RWreturn type_mark
               --    | RWfunction designator             RWreturn type_mark ;
               --
               -- designator :
               --      identifier ;

               Trace ("   generic subprogram body found");
               Unit_Type_Local   := ContextManager.GenericSubprogramBody;
               Name_Ptr          :=
                 STree.Child_Node
                 (Current_Node => STree.Child_Node
                    (Current_Node => STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Inherit_Ptr_Local))));
               Inherit_Ptr_Local := STree.NullNode;
               -- ASSUME Inherit_Ptr_Local = NULL
               -- ASSUME Name_Ptr = identifier
            else
               Unit_Type_Local   := ContextManager.InvalidUnit;
               Name_Ptr          := STree.NullNode;
               Inherit_Ptr_Local := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Inherit_Ptr_Local = package_body OR generic_subprogram_body in RequiredUnits.Init");
            end if;
            -- ASSUME Inherit_Ptr_Local = NULL
            -- ASSUME Name_Ptr = dotted_simple_name OR identifier
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.subunit then
            -- ASSUME Inherit_Ptr_Local = subunit

            -- subunit :
            --      RWseparate left_paren parent_unit_name right_paren proper_body ;
            --
            -- proper_body :
            --      subprogram_body | package_body | task_body | protected_body ;

            Trace ("   subunit found");
            Unit_Type_Local   := ContextManager.SubUnit;
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = parent_unit_name
            SystemErrors.RT_Assert
              (C       => STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.parent_unit_name,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Inherit_Ptr_Local = parent_unit_name in RequiredUnits.Init");
            Name_Ptr          := STree.Child_Node (Current_Node => STree.Next_Sibling (Current_Node => Inherit_Ptr_Local));
            Inherit_Ptr_Local := STree.Child_Node (Current_Node => Inherit_Ptr_Local);
            -- ASSUME Inherit_Ptr_Local = parent_unit_name OR simple_name
            SystemErrors.RT_Assert
              (C       => STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.parent_unit_name
                 or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.simple_name,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Inherit_Ptr_Local = parent_unit_name OR simple_name in RequiredUnits.Init");
            -- ASSUME Name_Ptr = subprogram_body OR package_body OR task_body OR protected_body
            if STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.subprogram_body then
               -- ASSUME Name_Ptr = subprogram_body

               -- subprogram_body :
               --      overriding_indicator procedure_specification procedure_annotation RWis subprogram_implementation
               --    | overriding_indicator function_specification  function_annotation  RWis subprogram_implementation
               --    |                      procedure_specification procedure_annotation RWis subprogram_implementation
               --    |                      function_specification  function_annotation  RWis subprogram_implementation ;

               Trace ("   subprogram body found");
               Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
               -- ASSUME Name_Ptr = procedure_specification OR function_specification OR overriding_indicator
               if STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.overriding_indicator then
                  Name_Ptr := STree.Next_Sibling (Current_Node => Name_Ptr);
               elsif STree.Syntax_Node_Type (Node => Name_Ptr) /= SP_Symbols.procedure_specification
                 and then STree.Syntax_Node_Type (Node => Name_Ptr) /= SP_Symbols.function_specification then
                  Name_Ptr := STree.NullNode;
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Name_Ptr = procedure_specification OR function_specification OR " &
                       "overriding_indicator in RequiredUnits.Init");
               end if;
               -- ASSUME Name_Ptr = procedure_specification OR function_specification
               SystemErrors.RT_Assert
                 (C       => STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.procedure_specification
                    or else STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.function_specification,
                  Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Name_Ptr = procedure_specification OR function_specification in RequiredUnits.Init");
               Name_Ptr := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Name_Ptr));
               -- ASSUME Name_Ptr = identifier
            elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.protected_body then
               -- ASSUME Name_Ptr = protected_body

               -- protected_body :
               --      RWprotected RWbody identifier RWis
               --        protected_operation_item
               --      RWend identifier semicolon ;

               Trace ("   protected body found");
               Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
               -- ASSUME Name_Ptr = identifier
            elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.task_body then
               -- ASSUME Name_Ptr = task_body

               -- task_body :
               --      RWtask RWbody identifier procedure_annotation RWis
               --        subprogram_implementation ;

               Trace ("   task body found");
               Name_Ptr := STree.Child_Node (Current_Node => Name_Ptr);
               -- ASSUME Name_Ptr = identifier
            elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.package_body then
               -- ASSUME Name_Ptr = package_body

               -- package_body :
               --      RWpackage RWbody dotted_simple_name                       RWis package_implementation semicolon
               --    | RWpackage RWbody dotted_simple_name refinement_definition RWis package_implementation semicolon ;

               Trace ("   separate package body found");
               Name_Ptr := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Name_Ptr));
               -- ASSUME Name_Ptr = dotted_simple_name OR identifier
            else
               Name_Ptr := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Name_Ptr = subprogram_body OR package_body OR task_body OR " &
                    "protected_body in RequiredUnits.Init");
            end if;
            -- ASSUME Inherit_Ptr_Local = parent_unit_name OR simple_name
            -- ASSUME Name_Ptr = dotted_simple_name OR identifier
         else
            Unit_Type_Local   := ContextManager.InvalidUnit;
            Inherit_Ptr_Local := STree.NullNode;
            Name_Ptr          := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Inherit_Ptr_Local = library_unit_body OR subunit in RequiredUnits.Init");
         end if;
         -- ASSUME Inherit_Ptr_Local = parent_unit_name OR simple_name OR NULL
         -- ASSUME Name_Ptr = dotted_simple_name OR identifier
      elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.apragma then
         -- ASSUME Inherit_Ptr_Local = apragma
         Trace ("   pragma found");
         Unit_Type_Local   := ContextManager.InterUnitPragma;
         Inherit_Ptr_Local := STree.NullNode;
         Name_Ptr          := STree.NullNode;
         -- ASSUME Inherit_Ptr_Local = NULL
         -- ASSUME Name_Ptr = NULL
      elsif STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.SPEND then
         -- ASSUME Inherit_Ptr_Local = SPEND
         Unit_Type_Local   := ContextManager.InvalidUnit;
         Inherit_Ptr_Local := STree.NullNode;
         Name_Ptr          := STree.NullNode;
         -- ASSUME Inherit_Ptr_Local = NULL
         -- ASSUME Name_Ptr = NULL
      else
         Unit_Type_Local   := ContextManager.InvalidUnit;
         Inherit_Ptr_Local := STree.NullNode;
         Name_Ptr          := STree.NullNode;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Inherit_Ptr_Local = library_unit OR secondary_unit OR apragma OR SPEND in RequiredUnits.Init");
      end if;
      -- ASSUME Inherit_Ptr_Local = inherit_clause_rep OR dotted_simple_name OR parent_unit_name OR simple_name OR NULL
      -- ASSUME Name_Ptr = dotted_simple_name OR identifier OR NULL
      if Name_Ptr = STree.NullNode then
         -- ASSUME Name_Ptr = NULL
         Unit_Name := LexTokenLists.Null_List;
      elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.dotted_simple_name then
         -- ASSUME Name_Ptr = dotted_simple_name
         Unit_Name_Local := LexTokenLists.Null_List;
         Name_Ptr        := STree.Last_Child_Of (Start_Node => Name_Ptr);
         loop
            -- ASSUME Name_Ptr = identifier
            LexTokenLists.Append (Unit_Name_Local, STree.Node_Lex_String (Node => Name_Ptr));
            Name_Ptr := STree.Next_Sibling (Current_Node => STree.Parent_Node (Current_Node => Name_Ptr));
            exit when STree.Syntax_Node_Type (Node => Name_Ptr) /= SP_Symbols.identifier;
         end loop;
         Unit_Name := Unit_Name_Local;
      elsif STree.Syntax_Node_Type (Node => Name_Ptr) = SP_Symbols.identifier then
         -- ASSUME Name_Ptr = identifier
         Unit_Name_Local := LexTokenLists.Null_List;
         LexTokenLists.Append (Unit_Name_Local, STree.Node_Lex_String (Node => Name_Ptr));
         Unit_Name := Unit_Name_Local;
      else
         Unit_Name := LexTokenLists.Null_List;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Name_Ptr = dotted_simple_name OR identifier OR NULL in RequiredUnits.Init");
      end if;
      Unit_Type := Unit_Type_Local;
      SystemErrors.RT_Assert
        (C       => Inherit_Ptr_Local = STree.NullNode
           or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.inherit_clause_rep
           or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.dotted_simple_name
           or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.parent_unit_name
           or else STree.Syntax_Node_Type (Node => Inherit_Ptr_Local) = SP_Symbols.simple_name,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Inherit_Ptr_Local = inherit_clause_rep OR dotted_simple_name OR parent_unit_name OR " &
           "simple_name OR NULL in RequiredUnits.Init");
      Inherit_Ptr := Inherit_Ptr_Local;
   end Init;

   procedure Next (Inherit_Ptr   : in out STree.SyntaxNode;
                   Required_Unit :    out LexTokenLists.Lists;
                   Found         :    out Boolean) is

      procedure CopyInheritedPackageToList (DottedNameNode : STree.SyntaxNode)
      --# global in     STree.Table;
      --#        in out Required_Unit;
      --# derives Required_Unit from *,
      --#                            DottedNameNode,
      --#                            STree.Table;
      is
         CurrentNode : STree.SyntaxNode;
      begin
         Trace ("Entering RequiredUnits.CopyInheritedPackageToList");
         CurrentNode := STree.Last_Child_Of (Start_Node => DottedNameNode);
         loop
            exit when CurrentNode = STree.NullNode;
            LexTokenLists.Append (List => Required_Unit,
                                  Item => STree.Node_Lex_String (Node => CurrentNode));
            CurrentNode := STree.Next_Sibling (Current_Node => STree.Parent_Node (Current_Node => CurrentNode));
         end loop;
      end CopyInheritedPackageToList;

      -------------------------------

      procedure CopyPUNtoList (PUNNode : in     STree.SyntaxNode;
                               List    :    out LexTokenLists.Lists)
      --# global in STree.Table;
      --# derives List from PUNNode,
      --#                   STree.Table;
      is
         NextNode : STree.SyntaxNode;
         LList    : LexTokenLists.Lists;
      begin
         NextNode := PUNNode;
         while STree.Syntax_Node_Type (Node => NextNode) /= SP_Symbols.simple_name loop
            NextNode := STree.Child_Node (Current_Node => NextNode);
         end loop;
         LList := LexTokenLists.Null_List;
         loop
            LexTokenLists.Append (LList, STree.Node_Lex_String (Node => STree.Child_Node (Current_Node => NextNode)));

            NextNode := STree.Next_Sibling (Current_Node => STree.Parent_Node (Current_Node => NextNode));
            exit when STree.Syntax_Node_Type (Node => NextNode) /= SP_Symbols.simple_name;
         end loop;
         List := LList;
      end CopyPUNtoList;

   begin -- Next
      Trace ("Entering RequiredUnits.Next");
      Required_Unit := LexTokenLists.Null_List;
      if Inherit_Ptr = STree.NullNode then
         Found := False;
      else
         Found := True;
         if STree.Syntax_Node_Type (Node => Inherit_Ptr) = SP_Symbols.simple_name then
            LexTokenLists.Append
              (List => Required_Unit,
               Item => STree.Node_Lex_String (Node => STree.Child_Node (Current_Node => Inherit_Ptr)));
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr) = SP_Symbols.dotted_simple_name then
            CopyInheritedPackageToList (Inherit_Ptr);
            Inherit_Ptr := STree.NullNode;
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr) = SP_Symbols.inherit_clause_rep then
            CopyInheritedPackageToList (STree.Next_Sibling (Current_Node => Inherit_Ptr));
            Inherit_Ptr := STree.Child_Node (Current_Node => Inherit_Ptr);
         elsif STree.Syntax_Node_Type (Node => Inherit_Ptr) = SP_Symbols.parent_unit_name then
            CopyPUNtoList (Inherit_Ptr, Required_Unit);
            Inherit_Ptr := STree.NullNode;
         end if;
      end if;
   end Next;

end RequiredUnits;
