-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

separate (Dictionary)
procedure Add_Record_Subcomponent
  (Prefix               : in     Symbol;
   The_Record_Component : in     RawDict.Record_Component_Info_Ref;
   Comp_Unit            : in     ContextManager.UnitDescriptors;
   The_Subcomponent     :    out RawDict.Subcomponent_Info_Ref) is
   Current_Subcomponent, Next_Subcomponent : RawDict.Subcomponent_Info_Ref;
   Valid_State                             : Boolean;
begin
   case RawDict.GetSymbolDiscriminant (Prefix) is
      when Variable_Symbol =>
         Current_Subcomponent :=
           RawDict.Get_Variable_Subcomponents (The_Variable => RawDict.Get_Variable_Info_Ref (Item => Prefix)); -- GAA External
         Valid_State          :=
           RawDict.Get_Variable_Marked_Valid (The_Variable => RawDict.Get_Variable_Info_Ref (Item => Prefix)); -- GAA External
      when Subprogram_Parameter_Symbol =>
         Current_Subcomponent :=
           RawDict.Get_Subprogram_Parameter_Subcomponents
           (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (Item => Prefix)); -- GAA External
         Valid_State          := True;
      when Subcomponent_Symbol =>
         Current_Subcomponent :=
           RawDict.Get_Subcomponent_Subcomponents
           (The_Subcomponent => RawDict.Get_Subcomponent_Info_Ref (Item => Prefix)); -- GAA External
         Valid_State          :=
           RawDict.Get_Subcomponent_Marked_Valid
           (The_Subcomponent => RawDict.Get_Subcomponent_Info_Ref (Item => Prefix)); -- GAA External
      when others => -- non-exec code
         Current_Subcomponent := RawDict.Null_Subcomponent_Info_Ref;
         Valid_State          := False;
         SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                                   Msg     => "in Dictionary.Add_Record_Subcomponent");
   end case;

   if Current_Subcomponent = RawDict.Null_Subcomponent_Info_Ref then
      -- no subcomponents at all
      RawDict.Create_Subcomponent
        (Object           => Prefix,
         Record_Component => The_Record_Component,
         Marked_Valid     => Valid_State,
         Comp_Unit        => Comp_Unit,
         Loc              => RawDict.Get_Symbol_Location (RawDict.Get_Record_Component_Symbol (The_Record_Component)),
         The_Subcomponent => The_Subcomponent);
      case RawDict.GetSymbolDiscriminant (Prefix) is
         when Variable_Symbol =>
            RawDict.Set_Variable_Subcomponents
              (The_Variable  => RawDict.Get_Variable_Info_Ref (Item => Prefix), -- GAA External
               Subcomponents => The_Subcomponent);
         when Subprogram_Parameter_Symbol =>
            RawDict.Set_Subprogram_Parameter_Subcomponents
              (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (Item => Prefix), -- GAA External
               Subcomponents            => The_Subcomponent);
         when Subcomponent_Symbol =>
            RawDict.Set_Subcomponent_Subcomponents
              (The_Subcomponent => RawDict.Get_Subcomponent_Info_Ref (Item => Prefix), -- GAA External
               Sibling          => The_Subcomponent);
         when others => -- non-exec code
            SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                                      Msg     => "in Dictionary.Add_Record_Subcomponent");
      end case;
   else -- at least one subcomponent already present
      loop
         --# assert Current_Subcomponent /= RawDict.Null_Subcomponent_Info_Ref;
         if RawDict.Get_Subcomponent_Record_Component (The_Subcomponent => Current_Subcomponent) = The_Record_Component then
            -- the one we are seeking to add is already present
            The_Subcomponent := Current_Subcomponent;
            exit;
         end if;

         Next_Subcomponent := RawDict.Get_Next_Subcomponent (The_Subcomponent => Current_Subcomponent);

         if Next_Subcomponent = RawDict.Null_Subcomponent_Info_Ref then
            -- checked all subcomponents and didn't find the one we want so add it
            RawDict.Create_Subcomponent
              (Object           => Prefix,
               Record_Component => The_Record_Component,
               Marked_Valid     => Valid_State,
               Comp_Unit        => Comp_Unit,
               Loc              => RawDict.Get_Symbol_Location (RawDict.Get_Subcomponent_Symbol (Current_Subcomponent)),
               The_Subcomponent => The_Subcomponent);
            RawDict.Set_Next_Subcomponent (The_Subcomponent => Current_Subcomponent,
                                           Next             => The_Subcomponent);
            exit;
         end if;
         Current_Subcomponent := Next_Subcomponent;
      end loop;
   end if;
end Add_Record_Subcomponent;
