-------------------------------------------------------------------------------
-- (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 (ErrorHandler.Conversions.ToString)
procedure AppendReference (E_Str     : in out E_Strings.T;
                           Reference : in     Natural) is
   subtype Index12 is Positive range 1 .. 12;
   subtype Paras is String (Index12);

   type References is record
      Source : Sources;
      Para   : Paras;
   end record;

   --e.g. ALRM 12.3.4(6) == References'(LRM, Paras'("12.3.4(6)   "));

   Empty_Reference : constant References := References'(Nul, Paras'("            "));

   Max_References : constant Positive := 22;  --INCREMENT WHEN ADDING REFS
   subtype Reference_Indexes is Positive range 1 .. Max_References;
   type Reference_Tables is array (Reference_Indexes, CommandLineData. Language_Profiles) of References;

   -- References arranged thus:
   --
   -- Ref_No => (Spark83-ref,
   --            Spark95-ref,
   --            Spark2005_Profiles-ref)

   Reference_Table : constant Reference_Tables :=
     Reference_Tables'
     (1  => (CommandLineData.SPARK83            => References'(LRM, Paras'("4.9         ")),
             CommandLineData.SPARK95            => Empty_Reference,
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      2  => (CommandLineData.SPARK83            => References'(LRM, Paras'("3.3.3(9)    ")),
             CommandLineData.SPARK95            => Empty_Reference,
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      3  => (CommandLineData.SPARK83            => References'(LRM, Paras'("3.6.1(3)    ")),
             CommandLineData.SPARK95            => Empty_Reference,
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      4  => (CommandLineData.SPARK83            => Empty_Reference,
             CommandLineData.SPARK95            => References'(LRM, Paras'("7.2(4)      ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      5  => (CommandLineData.SPARK83            => References'(SR83, Paras'("5.2.1       ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("5.2.1       ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      6  => (CommandLineData.SPARK83            => References'(SR83, Paras'("3.6.3       ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("3.6.3       ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      7  => (CommandLineData.SPARK83            => References'(SR83, Paras'("4.1         ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("4.1         ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      8  => (CommandLineData.SPARK83            => References'(LRM, Paras'("5.2(3)      ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("5.2(4)      ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      9  => (CommandLineData.SPARK83            => Empty_Reference,
             CommandLineData.SPARK95            => References'(LRM, Paras'("J.3         ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      10 => (CommandLineData.SPARK83            => References'(LRM, Paras'("3.2.2(1)    ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("3.3.2(3)    ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      11 => (CommandLineData.SPARK83            => References'(LRM, Paras'("6.3.1(5)    ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("6.3.1(18)   ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      12 => (CommandLineData.SPARK83            => References'(LRM, Paras'("7.4(4)      ")),
             CommandLineData.SPARK95            => Empty_Reference,
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      13 => (CommandLineData.SPARK83            => References'(SR83, Paras'("3.2(Note2)  ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("3.2(Note2)  ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      14 => (CommandLineData.SPARK83            => References'(LRM, Paras'("5.2(2)      ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("5.2(2)      ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      15 => (CommandLineData.SPARK83            => References'(SR83, Paras'("3.3.2       ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("3.3.2       ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      16 => (CommandLineData.SPARK83            => References'(SR83, Paras'("7.3.1       ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("7.3.1       ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      17 => (CommandLineData.SPARK83            => References'(LRM, Paras'("10.2(3)     ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("10.1.3(13)  ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      18 => (CommandLineData.SPARK83            => References'(SR83, Paras'("3.9(1)      ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("3.9(1)      ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      19 => (CommandLineData.SPARK83            => References'(SR83, Paras'("6.3         ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("6.3         ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      20 => (CommandLineData.SPARK83            => References'(SR83, Paras'("7.2.3       ")),
             CommandLineData.SPARK95            => References'(SR95, Paras'("7.2.3       ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      21 => (CommandLineData.SPARK83            => References'(LRM, Paras'("6.3(3)      ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("6.1(20)     ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference),
      22 => (CommandLineData.SPARK83            => References'(LRM, Paras'("4.6(3)      ")),
             CommandLineData.SPARK95            => References'(LRM, Paras'("4.6(61)     ")),
             CommandLineData.SPARK2005_Profiles => Empty_Reference));

   Current_Reference : References;

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

   procedure Append_Source (E_Str  : in out E_Strings.T;
                            Source : in     Sources)
   --# derives E_Str from *,
   --#                    Source;
   is
   begin
      case Source is
         when Nul =>
            null;
         when LRM =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "Ada LRM ");
         when SR83 =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "SR83 ");
         when SR95 =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "SR95 ");
         when UM =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "User Manual ");
         when Proof_UM =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "Proof Manual ");
         when JB =>
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "Barnes ");
      end case;
   end Append_Source;

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

   procedure Append_Para (E_Str : in out E_Strings.T;
                          Para  : in     Paras)
   --# derives E_Str from *,
   --#                    Para;
   is
   begin
      for I in Index12 loop
         exit when Para (I) = ' ';
         E_Strings.Append_Char (E_Str => E_Str,
                                Ch    => Para (I));
      end loop;
   end Append_Para;

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

begin --AppendReference
   if Reference /= ErrorHandler.No_Reference and not CommandLineData.Content.Plain_Output then

      if Reference > Max_References then
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " [Ref No Too High]");
      else
         Current_Reference := Reference_Table (Reference, CommandLineData.Content.Language_Profile);
         if Current_Reference /= Empty_Reference then
            Source_Used (Current_Reference.Source) := True;
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => " [");
            Append_Source (E_Str  => E_Str,
                           Source => Current_Reference.Source);
            Append_Para (E_Str => E_Str,
                         Para  => Current_Reference.Para);
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => "]");
         end if;
      end if;
   end if;
end AppendReference;
