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

--------------------------------------------------------------------------------
--Synopsis:                                                                   --
--                                                                            --
--Procedure to process type (1) lines for the VCS package                     --
--                                                                            --
--------------------------------------------------------------------------------

with VCDetails;

separate (VCS)
procedure ProcessNewRangeLine (Line    : in     E_Strings.T;
                               VC_Info : in out VC_Info_Type) is
   New_End_Line            : VC_Line_Type;
   New_Start_Line          : VC_Line_Type;
   New_VC_Info             : VC_Info_Type;
   New_End_Line_Point_Type : VCDetails.Terminal_Point_Type;

   ---------------------------------------------------------------------
   -- The first line specified in a line of type (1) is found as follows:
   -- If the line contains 'start' then that's it
   -- If the line contatin 'refinement' then that's it
   -- If the line contatin 'inheritance' then that's it
   -- otherwise find the first occurrence of 'line' and extract the number
   -- which follows
   function Extract_First_Line_In_Range (Line : E_Strings.T) return VC_Line_Type is
      Dummy_Position    : E_Strings.Positions;
      Line_Found        : Boolean;
      Line_Position     : E_Strings.Positions;
      Line_Number       : VC_Line_Type;
      Start_Found       : Boolean;
      Refinement_Found  : Boolean;
      Inheritance_Found : Boolean;
   begin -- Extract_First_Line_In_Range

      --# accept F, 10, Dummy_Position, "Dummy_Position unused here";
      E_Strings.Find_Sub_String
        (E_Str         => Line,
         Search_String => "inheritance",
         String_Found  => Inheritance_Found,
         String_Start  => Dummy_Position);

      E_Strings.Find_Sub_String
        (E_Str         => Line,
         Search_String => "refinement",
         String_Found  => Refinement_Found,
         String_Start  => Dummy_Position);

      E_Strings.Find_Sub_String
        (E_Str         => Line,
         Search_String => "start",
         String_Found  => Start_Found,
         String_Start  => Dummy_Position);
      --# end accept;

      if Refinement_Found or Inheritance_Found then
         Line_Number := Refinement_Or_Inheritance_VC;
      elsif Start_Found then
         Line_Number := VC_Line_Start;
      else
         --# accept F, 10, Line_Found, "Line_Found unused here";
         E_Strings.Find_Sub_String
           (E_Str         => Line,
            Search_String => "line",
            String_Found  => Line_Found,
            String_Start  => Line_Position);
         --# end accept;
         Line_Number := Extract_Line_Number_At_Position (Line      => Line,
                                                         Start_Pos => Line_Position + 5);
      end if;

      --# accept F, 33, Dummy_Position, "Dummy_Position unused here" &
      --#        F, 33, Line_Found, "Line_Found unused here";
      return Line_Number;
   end Extract_First_Line_In_Range;

   ---------------------------------------------------------------------
   -- the second line specified in a line of type (1) is found as follows:
   -- either find "finish", or find first occurrence of "line" after "start"
   -- or find second occurrence of "line"

   function Extract_Last_Line_In_Range (Line : E_Strings.T) return VC_Line_Type is
      Dummy_Position : E_Strings.Positions;
      Finish_Found   : Boolean;
      Line_Found     : Boolean;
      Line_Position  : E_Strings.Positions;
      Line_Number    : VC_Line_Type;
      First_Line_Pos : E_Strings.Positions;

      ---------------------------------------------------------------------
      -- this function returns the index of the string "start" in the line
      -- if this is not present, it returns the index of the first occurrence
      -- of "line"
      -- the action if neither is present is undefined
      function Position_Of_First_Line_Number (Line : E_Strings.T) return E_Strings.Positions is
         Line_Found     : Boolean;
         Line_Position  : E_Strings.Positions;
         Pos            : E_Strings.Positions;
         Start_Found    : Boolean;
         Start_Position : E_Strings.Positions;
      begin -- Position_Of_First_Line_Number
         E_Strings.Find_Sub_String
           (E_Str         => Line,
            Search_String => "start",
            String_Found  => Start_Found,
            String_Start  => Start_Position);
         if Start_Found then
            Pos := Start_Position;
         else
            --# accept F, 10, Line_Found, "Line_Found unused here";
            E_Strings.Find_Sub_String
              (E_Str         => Line,
               Search_String => "line",
               String_Found  => Line_Found,
               String_Start  => Line_Position);
            --# end accept;
            Pos := Line_Position;
         end if;

         --# accept F, 33, Line_Found, "Line_Found unused here";
         return Pos;
      end Position_Of_First_Line_Number;

      ---------------------------------------------------------------------
   begin -- Extract_Last_Line_In_Range

      --# accept F, 10, Dummy_Position, "Dummy_Position unused here";
      E_Strings.Find_Sub_String
        (E_Str         => Line,
         Search_String => "finish",
         String_Found  => Finish_Found,
         String_Start  => Dummy_Position);
      --# end accept;
      if Finish_Found then
         Line_Number := VC_Line_End;
      else

         -- find first line number
         First_Line_Pos := Position_Of_First_Line_Number (Line => Line);

         -- skip it and find second one
         --# accept F, 10, Line_Found, "Line_Found unused here";
         E_Strings.Find_Sub_String_After
           (E_Str         => Line,
            Search_Start  => First_Line_Pos + 5,
            Search_String => "line",
            String_Found  => Line_Found,
            String_Start  => Line_Position);
         --# end accept;
         Line_Number := Extract_Line_Number_At_Position (Line      => Line,
                                                         Start_Pos => Line_Position + 5);
      end if;

      --# accept F, 33, Dummy_Position, "Dummy_Position unused here" &
      --#        F, 33, Line_Found, "Line_Found unused here";
      return Line_Number;
   end Extract_Last_Line_In_Range;

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

begin -- ProcessNewRangeLine
   New_Start_Line := Extract_First_Line_In_Range (Line => Line);

   if New_Start_Line = Refinement_Or_Inheritance_VC then
      New_End_Line := Refinement_Or_Inheritance_VC;
   else
      New_End_Line := Extract_Last_Line_In_Range (Line => Line);
   end if;

   New_End_Line_Point_Type := VCDetails.Path_End_To_Path_Type (Line => Line);

   New_VC_Info :=
     VC_Info_Type'
     (Start_Line              => New_Start_Line,
      End_Line                => New_End_Line,
      End_Line_Point_Type     => New_End_Line_Point_Type,
      Number_Of_VCs           => 0,
      Valid                   => True,
      File_Type               => VC_Info.File_Type,
      Any_VCs_Printed         => False,
      This_Start_Line_Printed => False);

   VC_Info := New_VC_Info;
end ProcessNewRangeLine;
