-------------------------------------------------------------------------------
-- (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.Command_Line;
with E_Strings.Not_SPARK;
with GNAT.OS_Lib;
with OSFiling;

package body OSCommandLine
is
   --# hide OSCommandLine;
   -- Hide the fact that State has no concrete definition, and that we are making
   -- use of Ada.Command_Line and GNAT.OS_Lib.

   -- SwitchCharacter returns the command line switch character for the platform
   function SwitchCharacter return Character
   is
   begin
#if Target = "Intel_WinNT" then
      return '/';
#else
      return '-';
#end if;
   end SwitchCharacter;

   procedure Normalize_Pathname (InputFile  : in     E_Strings.T;
                                 InputDir   : in     E_Strings.T;
                                 ResultPath :    out E_Strings.T)
   is
   begin
      ResultPath := E_Strings.Copy_String
        (Str => GNAT.OS_Lib.Normalize_Pathname (Name           => E_Strings.Not_SPARK.Get_String (E_Str => InputFile),
                                                Directory      => E_Strings.Not_SPARK.Get_String (E_Str => InputDir),
                                                Resolve_Links  => True,
                                                Case_Sensitive => True));
   end Normalize_Pathname;

   procedure Read (Switches : out DataType)

   is
      Index      : Natural;   -- Index into the input argument string currently being processed
      ArgCount   : Natural;   -- How many command line arguments
      UnusedChar : Character; -- Dummy argument needed for calls to PopChar
   begin

      -- Use default values unless overridden by command line
      Switches := DefaultDataType;

      ArgCount := Ada.Command_Line.Argument_Count;

      -- Remember to pass correct data structure in the case where there are zero args
      Switches.StartDirectory := OSFiling.Get_Working_Directory;

      -- Assume things are fine until shown otherwise.
      Switches.Valid := True;

      -- Process each argument in turn
      -- Currently 7 switches are implemented:
      -- version, plain output, ignore dates, input directory, output file and short summary.

      for ArgIndex in Natural range 1 .. ArgCount loop

         Index := 1; -- First character in argument string being processed

         -- Every argument should start with a switch character.
         -- Fail if this argument does not.

         -- Allow both switch characters for the time being. (We still need the prepping and this test
         -- because '/' is not a valid switch character on Unix.)
         if (Ada.Command_Line.Argument (ArgIndex) (Index) = SwitchCharacter) or
            (Ada.Command_Line.Argument (ArgIndex) (Index) = '-') then

            -- Check the length of the argument before indexing into it.
            -- Every argument should be at least 2 characters.
            if (Ada.Command_Line.Argument (ArgIndex)'Length) > 1 then
               Index := Index + 1;
            else
               Switches.Valid := False;
               exit;
            end if;

            case Ada.Command_Line.Argument (ArgIndex) (Index) is
               when 'd' | 'D' =>

                  -- Next character must be '=', and there must be at least one character in the directory
                  -- name itself, so the argument length must be at least 4.
                  Index := Index + 1;
                  if (Ada.Command_Line.Argument (ArgIndex)'Length > 3) and then
                     (Ada.Command_Line.Argument (ArgIndex) (Index) = '=') then

                     -- Copy the input argument string into StartDirectory
                     Switches.StartDirectory := E_Strings.Copy_String (Str => Ada.Command_Line.Argument (ArgIndex));

                     -- Strip off the first three characters ("-d=")
                     E_Strings.Pop_Char (E_Str => Switches.StartDirectory,
                                         Char  => UnusedChar);
                     E_Strings.Pop_Char (E_Str => Switches.StartDirectory,
                                         Char  => UnusedChar);
                     E_Strings.Pop_Char (E_Str => Switches.StartDirectory,
                                         Char  => UnusedChar);

                  else
                     Switches.Valid := False;
                  end if;
               when 'o' | 'O' =>
                  -- Next character must be '=', and there must be at least one character in the file
                  -- name itself, so the argument length must be at least 4.
                  Index := Index + 1;
                  if (Ada.Command_Line.Argument (ArgIndex)'Length > 3) and then
                     (Ada.Command_Line.Argument (ArgIndex) (Index) = '=') then

                     -- Copy the input argument string into ReportFile
                     Switches.ReportFile := E_Strings.Copy_String (Str => Ada.Command_Line.Argument (ArgIndex));

                     -- Strip off the first three characters ("-o=")
                     E_Strings.Pop_Char (E_Str => Switches.ReportFile,
                                         Char  => UnusedChar);
                     E_Strings.Pop_Char (E_Str => Switches.ReportFile,
                                         Char  => UnusedChar);
                     E_Strings.Pop_Char (E_Str => Switches.ReportFile,
                                         Char  => UnusedChar);

                  else
                     Switches.Valid := False;
                  end if;
               when 'V' | 'v' =>
                  if Switches.VersionRequested or
                     ((Ada.Command_Line.Argument (ArgIndex)'Length) > 2) then
                     Switches.Valid := False;
                  else
                  -- use of this switch overrides any previously given -p
                     Switches.VersionRequested := True;
                     Switches.PlainOutput := False;
                  end if;
               when 'I' | 'i' =>
                  if Switches.IgnoreDates or
                     ((Ada.Command_Line.Argument (ArgIndex)'Length) > 2) then
                     Switches.Valid := False;
                  else
                     Switches.IgnoreDates := True;
                  end if;
               when 'P' | 'p' =>
                  if Switches.PlainOutput or
                     ((Ada.Command_Line.Argument (ArgIndex)'Length) > 2) then
                     Switches.Valid := False;
                  else
                  -- if -v already given, then ignore -p
                     if not Switches.VersionRequested then
                        Switches.PlainOutput := True;
                     end if;
                  end if;
               when 'S' | 's' =>
                  if Switches.ShortSummary or
                     ((Ada.Command_Line.Argument (ArgIndex)'Length) > 2) then
                     Switches.Valid := False;
                  else
                     Switches.ShortSummary := True;
                  end if;
               when others =>
                  Switches.Valid := False;

            end case;

         else
            Switches.Valid := False;
         end if;

      end loop;

   end Read;

end OSCommandLine;
